"use strict";
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use self file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const MLINDEX_BYTES_NUM_2 = 2;
const MLINDEX_BYTES_NUM_3 = 3;
const MLINDEX_BYTES_NUM_4 = 4;
const MLINDEX_BYTES_NUM_03 = 0.3;
const MLINDEX_BYTES_NUM_05 = 0.5;
const MLINDEX_BYTES_NUM_06745 = 0.6745;
const MLINDEX_BYTES_NUM_20 = 2.0;
const MLINDEX_BYTES_NUM_100 = 100;
const MLINDEX_BYTES_NUM_52 = -52;
const MLINDEX_BYTES_NUM_0520 = -52.0;
const MLINDEX_BYTES_NUM_1000 = 1000;
const MLINDEX_BYTES_NUM_512 = 512;
const MLINDEX_BYTES_NUM_10 = 10;
const MLINDEX_BYTES_NUM_50 = 50;
const MLINDEX_BYTES_NUM_75 = 75;
const MLINDEX_BYTES_NUM_075 = 0.75;
const MLINDEX_BYTES_NUM_04375 = -0.4375;
const MLINDEX_BYTES_NUM_30 = 30;
const MLINDEX_BYTES_NUM_0964 = 0.964;
const MLINDEX_BYTES_NUM_002 = -2;
const MLINDEX_BYTES_NUM_001 = 0.01;
const MLINDEX_BYTES_NUM_5 = 5;
const MLINDEX_BYTES_NUM_6 = 6;
const MLINDEX_BYTES_NUM_020 = 20;
const MLINDEX_BYTES_NUM_050 = 5.0;
const MLINDEX_BYTES_NUM_40 = 4.0;
const MLINDEX_BYTES_NUM_040 = 40;
const NUM_STIME_CONST = 1000;
const NUM_TIME_LOOP_CONST = 60;
const NUM_TIME_LOOP_5 = 5;
class MlOptions {
    constructor() {
        this.inPlace = true;
        this.max = 0;
        this.min = 0;
        this.from = 0;
        this.to = 0;
        this.numberOfPoints = 0;
        this.variant = '';
        this.computeLeftSingularVectors = false;
        this.computeRightSingularVectors = false;
        this.autoTranspose = false;
        this.hiddenLayers = [];
        this.assumeSymmetric = false;
        this.layers = [];
        this.defaultOptions = new Map();
        this.defaultOptions.set('assumeSymmetric', false);
    }
}
// ml-stat array.js
class MlStatArrayCls {
    compareNumbers(a, b) {
        return a - b;
    }
    sum(values) {
        let sum = 0;
        for (let i = 0; i < values.length; i++) {
            sum += values[i];
        }
        return sum;
    }
    max(values) {
        let max = values[0];
        let l = values.length;
        for (let i = 1; i < l; i++) {
            if (values[i] > max) {
                max = values[i];
            }
        }
        return max;
    }
    min(values) {
        let min = values[0];
        let l = values.length;
        for (let i = 1; i < l; i++) {
            if (values[i] < min) {
                min = values[i];
            }
        }
        return min;
    }
    minMax(values) {
        let min = values[0];
        let max = values[0];
        let l = values.length;
        for (let i = 1; i < l; i++) {
            if (values[i] < min) {
                min = values[i];
            }
            if (values[i] > max) {
                max = values[i];
            }
        }
        return [min, max];
    }
    arithmeticMean(values) {
        let sum = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            sum += values[i];
        }
        return sum / l;
    }
    mean(values) {
        return this.arithmeticMean(values);
    }
    geometricMean(values) {
        let mul = 1;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            mul *= values[i];
        }
        return Math.pow(mul, 1 / l);
    }
    logMean(values) {
        let lnsum = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            lnsum += Math.log(values[i]);
        }
        return lnsum / l;
    }
    grandMean(means, samples) {
        let sum = 0;
        let n = 0;
        let l = means.length;
        for (let i = 0; i < l; i++) {
            sum += samples[i] * means[i];
            n += samples[i];
        }
        return sum / n;
    }
    truncatedMean(values, percent, alreadySorted) {
        let newAlreadySorted = alreadySorted;
        let newValues = values;
        if (alreadySorted === undefined) {
            newAlreadySorted = false;
        }
        if (!newAlreadySorted) {
            newValues = newValues.sort(this.compareNumbers);
        }
        let l = newValues.length;
        let k = Math.floor(l * percent);
        let sum = 0;
        for (let i = k; i < l - k; i++) {
            sum += newValues[i];
        }
        return sum / (l - MLINDEX_BYTES_NUM_2 * k);
    }
    harmonicMean(values) {
        let sum = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            if (values[i] === 0) {
                throw new RangeError('value at index ' + i + 'is zero');
            }
            sum += 1 / values[i];
        }
        return l / sum;
    }
    contraHarmonicMean(values) {
        let r1 = 0;
        let r2 = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            r1 += values[i] * values[i];
            r2 += values[i];
        }
        if (r2 < 0) {
            throw new RangeError('sum of values is negative');
        }
        return r1 / r2;
    }
    median(values, alreadySorted) {
        let newAlreadySorted = alreadySorted;
        if (alreadySorted === undefined) {
            newAlreadySorted = false;
        }
        let newValues = values;
        if (!newAlreadySorted) {
            newValues = newValues.sort(this.compareNumbers);
        }
        let l = newValues.length;
        let half = Math.floor(l / MLINDEX_BYTES_NUM_2);
        if (l % MLINDEX_BYTES_NUM_2 === 0) {
            return (newValues[half - 1] + newValues[half]) * MLINDEX_BYTES_NUM_05;
        }
        else {
            return newValues[half];
        }
    }
    variance(values, unbiased) {
        let newUnbiased = unbiased;
        if (unbiased === undefined) {
            newUnbiased = true;
        }
        let theMean = this.mean(values);
        let theVariance = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            let x = values[i] - theMean;
            theVariance += x * x;
        }
        if (newUnbiased) {
            return theVariance / (l - 1);
        }
        else {
            return theVariance / l;
        }
    }
    standardDeviation(values, unbiased) {
        return Math.sqrt(this.variance(values, unbiased));
    }
    standardError(values) {
        return this.standardDeviation(values) / Math.sqrt(values.length);
    }
    robustMeanAndStdev(y) {
        let mean = 0;
        let stdev = 0;
        let length = y.length;
        for (let i = 0; i < length; i++) {
            mean += y[i];
        }
        mean /= length;
        let averageDeviations = Array(length).fill(0);
        for (let i = 0; i < length; i++) {
            averageDeviations[i] = Math.abs(y[i] - mean);
        }
        averageDeviations.sort(this.compareNumbers);
        if (length % MLINDEX_BYTES_NUM_2 === 1) {
            stdev = averageDeviations[(length - 1) / MLINDEX_BYTES_NUM_2] / MLINDEX_BYTES_NUM_06745;
        }
        else {
            stdev =
                (MLINDEX_BYTES_NUM_05 * (averageDeviations[length / MLINDEX_BYTES_NUM_2] + averageDeviations[length / MLINDEX_BYTES_NUM_2 - 1])) /
                    MLINDEX_BYTES_NUM_06745;
        }
        return [mean, stdev];
    }
    quartiles(values, alreadySorted) {
        let newAlreadySorted = alreadySorted;
        if (typeof alreadySorted === 'undefined') {
            newAlreadySorted = false;
        }
        let newValues = values;
        if (!newAlreadySorted) {
            newValues = newValues.sort(this.compareNumbers);
        }
        let quart = newValues.length / MLINDEX_BYTES_NUM_4;
        let q1 = newValues[Math.ceil(quart) - 1];
        let q2 = this.median(newValues, true);
        let q3 = newValues[Math.ceil(quart * MLINDEX_BYTES_NUM_3) - 1];
        return [q1, q2, q3];
    }
    pooledStandardDeviation(samples, unbiased) {
        return Math.sqrt(this.pooledVariance(samples, unbiased));
    }
    pooledVariance(samples, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let sum = 0;
        let count = 0;
        let l = samples.length;
        for (let i = 0; i < l; i++) {
            let values = samples[i];
            let vari = this.variance(values);
            sum += (values.length - 1) * vari;
            if (newUnbiased) {
                count += values.length - 1;
            }
            else {
                count += values.length;
            }
        }
        return sum / count;
    }
    mode(values) {
        let l = values.length;
        let itemCount = Array(l).fill(0);
        for (let i = 0; i < l; i++) {
            itemCount[i] = 0;
        }
        let itemArray = Array(l).fill(0);
        let count = 0;
        for (let i = 0; i < l; i++) {
            let index = itemArray.indexOf(values[i]);
            if (index >= 0) {
                itemCount[index] += 1;
            }
            else {
                itemArray[count] = values[i];
                itemCount[count] = 1;
                count += 1;
            }
        }
        let maxValue = 0;
        let maxIndex = 0;
        for (let i = 0; i < count; i++) {
            if (itemCount[i] > maxValue) {
                maxValue = itemCount[i];
                maxIndex = i;
            }
        }
        return itemArray[maxIndex];
    }
    covariance(vector1, vector2, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let mean1 = this.mean(vector1);
        let mean2 = this.mean(vector2);
        if (vector1.length !== vector2.length) {
            throw new RangeError('Vectors do not have the same dimensions');
        }
        let cov = 0;
        let l = vector1.length;
        for (let i = 0; i < l; i++) {
            let x = vector1[i] - mean1;
            let y = vector2[i] - mean2;
            cov += x * y;
        }
        if (newUnbiased) {
            return cov / (l - 1);
        }
        else {
            return cov / l;
        }
    }
    skewness(values, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let theMean = this.mean(values);
        let s2 = 0;
        let s3 = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            let dev = values[i] - theMean;
            s2 += dev * dev;
            s3 += dev * dev * dev;
        }
        let m2 = s2 / l;
        let m3 = s3 / l;
        let g = m3 / Math.pow(m2, MLINDEX_BYTES_NUM_3 / MLINDEX_BYTES_NUM_20);
        if (newUnbiased) {
            let a = Math.sqrt(l * (l - 1));
            let b = l - MLINDEX_BYTES_NUM_2;
            return (a / b) * g;
        }
        else {
            return g;
        }
    }
    kurtosis(values, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let theMean = this.mean(values);
        let n = values.length;
        let s2 = 0;
        let s4 = 0;
        for (let i = 0; i < n; i++) {
            let dev = values[i] - theMean;
            s2 += dev * dev;
            s4 += dev * dev * dev * dev;
        }
        let m2 = s2 / n;
        let m4 = s4 / n;
        if (newUnbiased) {
            let v = s2 / (n - 1);
            let a = (n * (n + 1)) / ((n - 1) * (n - MLINDEX_BYTES_NUM_2) * (n - MLINDEX_BYTES_NUM_3));
            let b = s4 / (v * v);
            let c = ((n - 1) * (n - 1)) / ((n - MLINDEX_BYTES_NUM_2) * (n - MLINDEX_BYTES_NUM_3));
            return a * b - MLINDEX_BYTES_NUM_3 * c;
        }
        else {
            return m4 / (m2 * m2) - MLINDEX_BYTES_NUM_3;
        }
    }
    entropy(values, eps) {
        let newEps = eps;
        if (typeof eps === 'undefined') {
            newEps = 0;
        }
        let sum = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            sum += values[i] * Math.log(values[i] + newEps);
        }
        return -sum;
    }
    weightedMean(values, weights) {
        let sum = 0;
        let l = values.length;
        for (let i = 0; i < l; i++) {
            sum += values[i] * weights[i];
        }
        return sum;
    }
    weightedStandardDeviation(values, weights) {
        return Math.sqrt(this.weightedVariance(values, weights));
    }
    weightedVariance(values, weights) {
        let theMean = this.weightedMean(values, weights);
        let vari = 0;
        let l = values.length;
        let a = 0;
        let b = 0;
        for (let i = 0; i < l; i++) {
            let z = values[i] - theMean;
            let w = weights[i];
            vari += w * (z * z);
            b += w;
            a += w * w;
        }
        return vari * (b / (b * b - a));
    }
    center(values, inPlace) {
        let newInPlace = inPlace;
        if (typeof inPlace === 'undefined') {
            newInPlace = false;
        }
        let result = values;
        if (!newInPlace) {
            result = values;
        }
        let theMean = this.mean(result);
        let l = result.length;
        for (let i = 0; i < l; i++) {
            result[i] -= theMean;
        }
    }
    standardize(values, standardDev, inPlace) {
        let newStandardDev = standardDev;
        let newInPlace = inPlace;
        if (typeof standardDev === 'undefined') {
            newStandardDev = this.standardDeviation(values);
        }
        if (typeof inPlace === 'undefined') {
            newInPlace = false;
        }
        let l = values.length;
        let result = newInPlace ? values : new Array(l);
        for (let i = 0; i < l; i++) {
            result[i] = values[i] / newStandardDev;
        }
        return result;
    }
    cumulativeSum(array) {
        let l = array.length;
        let result = Array(l).fill(0);
        result[0] = array[0];
        for (let i = 1; i < l; i++) {
            result[i] = result[i - 1] + array[i];
        }
        return result;
    }
}
let mlStatArray = new MlStatArrayCls();
class MlStatMatrixCls {
    compareNumbers(a, b) {
        return a - b;
    }
    max(matrix) {
        let max = Number.NEGATIVE_INFINITY;
        for (let i = 0; i < matrix.length; i++) {
            for (let j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] > max) {
                    max = matrix[i][j];
                }
            }
        }
        return max;
    }
    min(matrix) {
        let min = Number.POSITIVE_INFINITY;
        for (let i = 0; i < matrix.length; i++) {
            for (let j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] < min) {
                    min = matrix[i][j];
                }
            }
        }
        return min;
    }
    minMax(matrix) {
        let min = Number.POSITIVE_INFINITY;
        let max = Number.NEGATIVE_INFINITY;
        for (let i = 0; i < matrix.length; i++) {
            for (let j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] < min) {
                    min = matrix[i][j];
                }
                if (matrix[i][j] > max) {
                    max = matrix[i][j];
                }
            }
        }
        return [min, max];
    }
    entropy(matrix, eps) {
        let newEps = eps;
        if (typeof eps === 'undefined') {
            newEps = 0;
        }
        let sum = 0;
        let l1 = matrix.length;
        let l2 = matrix[0].length;
        for (let i = 0; i < l1; i++) {
            for (let j = 0; j < l2; j++) {
                sum += matrix[i][j] * Math.log(matrix[i][j] + newEps);
            }
        }
        return -sum;
    }
    mean(matrix, dimension) {
        let newDimension = dimension;
        if (typeof dimension === 'undefined') {
            newDimension = 0;
        }
        let rows = matrix.length;
        let cols = matrix[0].length;
        let theMean;
        let n;
        if (dimension === -1) {
            theMean = [0];
            n = rows * cols;
            for (let i = 0; i < rows; i++) {
                for (let j = 0; j < cols; j++) {
                    theMean[0] += matrix[i][j];
                }
            }
            theMean[0] /= n;
        }
        else if (newDimension === 0) {
            theMean = Array(cols).fill(0);
            n = rows;
            for (let j = 0; j < cols; j++) {
                theMean[j] = 0;
                for (let i = 0; i < rows; i++) {
                    theMean[j] += matrix[i][j];
                }
                theMean[j] /= n;
            }
        }
        else if (newDimension === 1) {
            theMean = Array(rows).fill(0);
            n = cols;
            for (let j = 0; j < rows; j++) {
                theMean[j] = 0;
                for (let i = 0; i < cols; i++) {
                    theMean[j] += matrix[j][i];
                }
                theMean[j] /= n;
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        return theMean;
    }
    sum(matrix, dimension) {
        let newDimension = dimension;
        if (typeof dimension === 'undefined') {
            newDimension = 0;
        }
        let rows = matrix.length;
        let cols = matrix[0].length;
        let theSum;
        if (newDimension === -1) {
            theSum = [0];
            for (let i = 0; i < rows; i++) {
                for (let j = 0; j < cols; j++) {
                    theSum[0] += matrix[i][j];
                }
            }
        }
        else if (newDimension === 0) {
            theSum = Array(cols).fill(0);
            for (let j = 0; j < cols; j++) {
                theSum[j] = 0;
                for (let i = 0; i < rows; i++) {
                    theSum[j] += matrix[i][j];
                }
            }
        }
        else if (newDimension === 1) {
            theSum = Array(rows).fill(0);
            for (let j = 0; j < rows; j++) {
                theSum[j] = 0;
                for (let i = 0; i < cols; i++) {
                    theSum[j] += matrix[j][i];
                }
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        return theSum;
    }
    product(matrix, dimension) {
        let newDimension = dimension;
        if (dimension === undefined) {
            newDimension = 0;
        }
        let rows = matrix.length;
        let cols = matrix[0].length;
        let theProduct;
        if (newDimension === -1) {
            theProduct = [1];
            for (let i = 0; i < rows; i++) {
                for (let j = 0; j < cols; j++) {
                    theProduct[0] *= matrix[i][j];
                }
            }
        }
        else if (newDimension === 0) {
            theProduct = Array(cols).fill(0);
            for (let j = 0; j < cols; j++) {
                theProduct[j] = 1;
                for (let i = 0; i < rows; i++) {
                    theProduct[j] *= matrix[i][j];
                }
            }
        }
        else if (newDimension === 1) {
            theProduct = Array(rows).fill(0);
            for (let j = 0; j < rows; j++) {
                theProduct[j] = 1;
                for (let i = 0; i < cols; i++) {
                    theProduct[j] *= matrix[j][i];
                }
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        return theProduct;
    }
    standardDeviation(matrix, means, unbiased) {
        let vari = this.variance(matrix, means, unbiased);
        let l = vari.length;
        for (let i = 0; i < l; i++) {
            vari[i] = Math.sqrt(vari[i]);
        }
        return vari;
    }
    variance(matrix, means, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let newMeans = means;
        if (typeof newMeans === 'undefined') {
            newMeans = this.mean(matrix);
        }
        let rows = matrix.length;
        if (rows === 0) {
            return new Array();
        }
        let cols = matrix[0].length;
        let vari = Array(cols).fill(0.0);
        for (let j = 0; j < cols; j++) {
            let sum1 = 0;
            let sum2 = 0;
            let x = 0;
            for (let i = 0; i < rows; i++) {
                x = matrix[i][j] - newMeans[j];
                sum1 += x;
                sum2 += x * x;
            }
            if (newUnbiased) {
                vari[j] = (sum2 - (sum1 * sum1) / rows) / (rows - 1);
            }
            else {
                vari[j] = (sum2 - (sum1 * sum1) / rows) / rows;
            }
        }
        return vari;
    }
    median(matrix) {
        let rows = matrix.length;
        let cols = matrix[0].length;
        let medians = Array(cols).fill(0);
        for (let i = 0; i < cols; i++) {
            let data = Array(rows).fill(0);
            for (let j = 0; j < rows; j++) {
                data[j] = matrix[j][i];
            }
            data.sort(this.compareNumbers);
            let n = data.length;
            if (n % MLINDEX_BYTES_NUM_2 === 0) {
                medians[i] = (data[n / MLINDEX_BYTES_NUM_2] + data[n / MLINDEX_BYTES_NUM_2 - 1]) * MLINDEX_BYTES_NUM_05;
            }
            else {
                medians[i] = data[Math.floor(n / MLINDEX_BYTES_NUM_2)];
            }
        }
        return medians;
    }
    mode(matrix) {
        let rows = matrix.length;
        let cols = matrix[0].length;
        let modes = Array(cols).fill(0);
        for (let i = 0; i < cols; i++) {
            let itemCount = Array(rows).fill(0);
            for (let k = 0; k < rows; k++) {
                itemCount[k] = 0;
            }
            let itemArray = Array(rows).fill(0);
            let count = 0;
            for (let j = 0; j < rows; j++) {
                let index = itemArray.indexOf(matrix[j][i]);
                if (index >= 0) {
                    itemCount[index] += 1;
                }
                else {
                    itemArray[count] = matrix[j][i];
                    itemCount[count] = 1;
                    count += 1;
                }
            }
            let maxValue = 0;
            let maxIndex = 0;
            for (let j = 0; j < count; j++) {
                if (itemCount[j] > maxValue) {
                    maxValue = itemCount[j];
                    maxIndex = j;
                }
            }
            modes[i] = itemArray[maxIndex];
        }
        return modes;
    }
    skewness(matrix, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let means = this.mean(matrix);
        let n = matrix.length;
        let l = means.length;
        let skew = new Array(l).fill(0.0);
        for (let j = 0; j < l; j++) {
            let s2 = 0;
            let s3 = 0;
            for (let i = 0; i < n; i++) {
                let dev = matrix[i][j] - means[j];
                s2 += dev * dev;
                s3 += dev * dev * dev;
            }
            let m2 = s2 / n;
            let m3 = s3 / n;
            let g = m3 / Math.pow(m2, MLINDEX_BYTES_NUM_3 / MLINDEX_BYTES_NUM_2);
            if (newUnbiased) {
                let a = Math.sqrt(n * (n - 1));
                let b = n - MLINDEX_BYTES_NUM_2;
                skew[j] = (a / b) * g;
            }
            else {
                skew[j] = g;
            }
        }
        return skew;
    }
    kurtosis(matrix, unbiased) {
        let newUnbiased = unbiased;
        if (typeof unbiased === 'undefined') {
            newUnbiased = true;
        }
        let means = this.mean(matrix);
        let n = matrix.length;
        let m = matrix[0].length;
        let kurt = new Array(m).fill(0);
        for (let j = 0; j < m; j++) {
            let s2 = 0;
            let s4 = 0;
            for (let i = 0; i < n; i++) {
                let dev = matrix[i][j] - means[j];
                s2 += dev * dev;
                s4 += dev * dev * dev * dev;
            }
            let m2 = s2 / n;
            let m4 = s4 / n;
            if (newUnbiased) {
                let v = s2 / (n - 1);
                let a = (n * (n + 1)) / ((n - 1) * (n - MLINDEX_BYTES_NUM_2) * (n - MLINDEX_BYTES_NUM_3));
                let b = s4 / (v * v);
                let c = ((n - 1) * (n - 1)) / ((n - MLINDEX_BYTES_NUM_2) * (n - MLINDEX_BYTES_NUM_3));
                kurt[j] = a * b - MLINDEX_BYTES_NUM_3 * c;
            }
            else {
                kurt[j] = m4 / (m2 * m2) - MLINDEX_BYTES_NUM_3;
            }
        }
        return kurt;
    }
    standardError(matrix) {
        let samples = matrix.length;
        let standardDeviations = this.standardDeviation(matrix);
        let l = standardDeviations.length;
        let standardErrors = Array(l).fill(0);
        let sqrtN = Math.sqrt(samples);
        for (let i = 0; i < l; i++) {
            standardErrors[i] = standardDeviations[i] / sqrtN;
        }
        return standardErrors;
    }
    covariance(matrix, dimension) {
        return this.scatter(matrix, undefined, dimension);
    }
    scatter(matrix, divisor, dimension) {
        let newDimension = dimension;
        let newDivisor = divisor;
        if (typeof dimension === 'undefined') {
            newDimension = 0;
        }
        if (typeof divisor === 'undefined') {
            if (newDimension === 0) {
                newDivisor = matrix.length - 1;
            }
            else if (dimension === 1) {
                newDivisor = matrix[0].length - 1;
            }
        }
        let means = this.mean(matrix, dimension);
        let rows = matrix.length;
        if (rows === 0) {
            return [[]];
        }
        let cols = matrix[0].length;
        let cov;
        let s;
        if (newDimension === 0) {
            cov = Array(cols).fill([0]);
            for (let i = 0; i < cols; i++) {
                cov[i] = Array(cols).fill(0);
            }
            for (let i = 0; i < cols; i++) {
                for (let j = i; j < cols; j++) {
                    s = 0;
                    for (let k = 0; k < rows; k++) {
                        s += (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
                    }
                    s /= Number(newDivisor);
                    cov[i][j] = s;
                    cov[j][i] = s;
                }
            }
        }
        else if (newDimension === 1) {
            cov = Array(rows).fill([0]);
            for (let i = 0; i < rows; i++) {
                cov[i] = Array(rows).fill(0);
            }
            for (let i = 0; i < rows; i++) {
                for (let j = i; j < rows; j++) {
                    s = 0;
                    for (let k = 0; k < cols; k++) {
                        s += (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
                    }
                    s /= Number(newDivisor);
                    cov[i][j] = s;
                    cov[j][i] = s;
                }
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        return cov;
    }
    correlation(matrix) {
        let means = this.mean(matrix);
        let standardDeviations = this.standardDeviation(matrix, means, true);
        let scores = this.zScores(matrix, means, standardDeviations);
        let rows = matrix.length;
        let cols = matrix[0].length;
        let cor = Array(cols).fill([0]);
        for (let i = 0; i < cols; i++) {
            cor[i] = Array(cols).fill(0);
        }
        for (let i = 0; i < cols; i++) {
            for (let j = i; j < cols; j++) {
                let c = 0;
                for (let k = 0; k < scores.length; k++) {
                    c += scores[k][j] * scores[k][i];
                }
                c /= rows - 1;
                cor[i][j] = c;
                cor[j][i] = c;
            }
        }
        return cor;
    }
    zScores(matrix, means, standardDeviations) {
        let newStandardDeviations = standardDeviations;
        let newMeans = means;
        if (typeof means === 'undefined') {
            newMeans = this.mean(matrix);
        }
        if (typeof standardDeviations === 'undefined') {
            newStandardDeviations = this.standardDeviation(matrix, newMeans, true);
        }
        return this.standardize(this.center(matrix, newMeans, false), newStandardDeviations, true);
    }
    center(matrix, means, inPlace) {
        let newMeans = means;
        if (typeof means === 'undefined') {
            newMeans = this.mean(matrix);
        }
        let result = matrix;
        let l = matrix.length;
        if (!inPlace) {
            result = new Array(l).fill([0]);
            for (let i = 0; i < l; i++) {
                result[i] = Array(matrix[i].length).fill(0);
            }
        }
        for (let i = 0; i < l; i++) {
            let row = result[i];
            for (let j = 0; j < row.length; j++) {
                row[j] = matrix[i][j] - newMeans[j];
            }
        }
        return result;
    }
    standardize(matrix, standardDeviations, inPlace) {
        let newStandardDeviations = standardDeviations;
        if (typeof standardDeviations === 'undefined') {
            newStandardDeviations = this.standardDeviation(matrix);
        }
        let result = matrix;
        let l = matrix.length;
        if (!inPlace) {
            result = new Array(l).fill([0]);
            for (let i = 0; i < l; i++) {
                result[i] = Array(matrix[i].length).fill(0);
            }
        }
        for (let i = 0; i < l; i++) {
            let resultRow = result[i];
            let sourceRow = matrix[i];
            for (let j = 0; j < resultRow.length; j++) {
                if (standardDeviations[j] !== 0) {
                    resultRow[j] = sourceRow[j] / newStandardDeviations[j];
                }
            }
        }
        return result;
    }
    weightedVariance(matrix, weights) {
        let means = this.mean(matrix);
        let rows = matrix.length;
        if (rows === 0) {
            return [];
        }
        let cols = matrix[0].length;
        let vari = Array(cols).fill(0);
        for (let j = 0; j < cols; j++) {
            let sum = 0;
            let a = 0;
            let b = 0;
            for (let i = 0; i < rows; i++) {
                let z = matrix[i][j] - means[j];
                let w = weights[i];
                sum += w * (z * z);
                b += w;
                a += w * w;
            }
            vari[j] = sum * (b / (b * b - a));
        }
        return vari;
    }
    weightedMean(matrix, weights, dimension) {
        let newDimension = dimension;
        if (typeof dimension === 'undefined') {
            newDimension = 0;
        }
        let rows = matrix.length;
        if (rows === 0) {
            return [];
        }
        let cols = matrix[0].length;
        let means;
        let w;
        let row;
        if (newDimension === 0) {
            means = Array(cols).fill(0);
            for (let i = 0; i < cols; i++) {
                means[i] = 0;
            }
            for (let i = 0; i < rows; i++) {
                row = matrix[i];
                w = weights[i];
                for (let j = 0; j < cols; j++) {
                    means[j] += row[j] * w;
                }
            }
        }
        else if (newDimension === 1) {
            means = Array(rows).fill(0);
            for (let i = 0; i < rows; i++) {
                means[i] = 0;
            }
            for (let j = 0; j < rows; j++) {
                row = matrix[j];
                w = weights[j];
                for (let i = 0; i < cols; i++) {
                    means[j] += row[i] * w;
                }
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        let weightSum = mlStatArray.sum(weights);
        if (weightSum !== 0) {
            for (let i = 0; i < means.length; i++) {
                means[i] /= weightSum;
            }
        }
        return means;
    }
    weightedCovariance(matrix, weights, means, dimension) {
        let newMeans = means;
        let newDimension = dimension;
        if (typeof dimension === 'undefined') {
            newDimension = 0;
        }
        if (typeof newMeans === 'undefined') {
            newMeans = this.weightedMean(matrix, weights, dimension);
        }
        let s1 = 0;
        let s2 = 0;
        for (let i = 0; i < weights.length; i++) {
            s1 += weights[i];
            s2 += weights[i] * weights[i];
        }
        let factor = s1 / (s1 * s1 - s2);
        return this.weightedScatter(matrix, weights, newMeans, factor, newDimension);
    }
    weightedScatter(matrix, weights, means, factor, dimension) {
        let newDimension = dimension;
        let newMeans = means;
        let newFactor = factor;
        if (typeof newDimension === 'undefined') {
            newDimension = 0;
        }
        if (typeof newMeans === 'undefined') {
            newMeans = this.weightedMean(matrix, weights, newDimension);
        }
        if (typeof factor === 'undefined') {
            newFactor = 1;
        }
        let rows = matrix.length;
        if (rows === 0) {
            return [[]];
        }
        let cols = matrix[0].length;
        let cov;
        let s;
        if (newDimension === 0) {
            cov = Array(cols).fill(0);
            for (let i = 0; i < cols; i++) {
                cov[i] = Array(cols).fill(0);
            }
            for (let i = 0; i < cols; i++) {
                for (let j = i; j < cols; j++) {
                    s = 0;
                    for (let k = 0; k < rows; k++) {
                        s += weights[k] * (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
                    }
                    cov[i][j] = s * factor;
                    cov[j][i] = s * factor;
                }
            }
        }
        else if (newDimension === 1) {
            cov = Array(rows).fill([0]);
            for (let i = 0; i < rows; i++) {
                cov[i] = Array(rows).fill(0);
            }
            for (let i = 0; i < rows; i++) {
                for (let j = i; j < rows; j++) {
                    s = 0;
                    for (let k = 0; k < cols; k++) {
                        s += weights[k] * (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
                    }
                    cov[i][j] = s * newFactor;
                    cov[j][i] = s * newFactor;
                }
            }
        }
        else {
            throw new Error('Invalid dimension');
        }
        return cov;
    }
}
let mlStatMatrix = new MlStatMatrixCls();
// ml-array-utils ArrayUtils.js
class MlArrayUtilsCls {
    getEquallySpacedData(x, y, options) {
        return mlArrayUtilsGetEquallySpaced.getEquallySpacedData(x, y, options);
    }
    snv(data) {
        let mean = mlStatArray.mean(data);
        let std = mlStatArray.standardDeviation(data);
        let result = [...data];
        for (let i = 0; i < data.length; i++) {
            result[i] = (result[i] - mean) / std;
        }
        return result;
    }
}
let mlArrayUtils = new MlArrayUtilsCls();
// ml-array-utils getEquallySpaced.js
class MlArrayUtilsGetEquallySpacedCls {
    getEquallySpacedData(x, y, options) {
        let newOptions = options;
        let newX = x;
        let newY = y;
        if (x.length > 1 && x[0] > x[1]) {
            newX = [...x.reverse()];
            newY = [...y.reverse()];
        }
        let xLength = x.length;
        if (xLength !== y.length) {
            throw new RangeError("the x and y vector does't have the same size.");
        }
        let from;
        if (options === undefined) {
            newOptions = new MlOptions();
        }
        if ((newOptions === null || newOptions === void 0 ? void 0 : newOptions.from) === 0) {
            from = Number(x[0]);
        }
        else {
            from = newOptions.from;
        }
        let to = newOptions.to === undefined ? newX[newX.length - 1] : newOptions.to;
        let reverse = from > to;
        if (reverse) {
            let temp = from;
            from = to;
            to = temp;
        }
        let numberOfPoints = newOptions.numberOfPoints === undefined ? MLINDEX_BYTES_NUM_100 : newOptions.numberOfPoints;
        let algorithm = newOptions.variant === 'slot' ? 'slot' : 'smooth'; // default value: smooth
        let output = algorithm === 'slot' ?
            this.getEquallySpacedSlot(newX, newY, Number(from), Number(to), numberOfPoints) :
            this.getEquallySpacedSmooth(newX, newY, Number(from), Number(to), numberOfPoints);
        if (reverse) {
            return output.reverse();
        }
        else {
            return output;
        }
    }
    getSlope(x0, y0, x1, y1) {
        return (y1 - y0) / (x1 - x0);
    }
    getEquallySpacedSmooth(x, y, from, to, numberOfPoints) {
        let xLength = x.length;
        let step = (to - from) / Number(numberOfPoints - 1);
        let halfStep = step / MLINDEX_BYTES_NUM_2;
        let start = from - halfStep;
        let output = Array(numberOfPoints).fill(0);
        let initialOriginalStep = x[1] - x[0];
        let lastOriginalStep = x[x.length - 1] - x[x.length - MLINDEX_BYTES_NUM_2];
        let min = start;
        let max = start + step;
        let previousX = Number.MIN_VALUE;
        let previousY = 0;
        let nextX = x[0] - initialOriginalStep;
        let nextY = 0;
        let currentValue = 0;
        let slope = 0;
        let intercept = 0;
        let sumAtMin = 0;
        let sumAtMax = 0;
        let i = 0;
        let j = 0;
        let mainWhile = true;
        main: while (mainWhile) {
            while (nextX - Number(max) >= 0) {
                // no overlap with original point, just consume current value
                let add = this.integral(0, Number(Number(max) - previousX), Number(slope), Number(previousY));
                sumAtMax = currentValue + add;
                output[j] = (sumAtMax - sumAtMin) / Number(step);
                j += 1;
                if (j === numberOfPoints) {
                    break main;
                }
                min = max;
                max += step;
                sumAtMin = sumAtMax;
            }
            if (previousX <= Number(min) && Number(min) <= nextX) {
                let add = this.integral(0, Number(Number(min) - previousX), Number(slope), Number(previousY));
                sumAtMin = currentValue + add;
            }
            currentValue += this.integral(Number(previousX), Number(nextX), Number(slope), Number(intercept));
            previousX = nextX;
            previousY = nextY;
            if (i < xLength) {
                nextX = x[i];
                nextY = y[i];
                i += 1;
            }
            else if (i === xLength) {
                nextX += lastOriginalStep;
                nextY = 0;
            }
            // updating parameters
            slope = this.getSlope(previousX, previousY, nextX, nextY);
            intercept = -slope * previousX + previousY;
        }
        return output;
    }
    getEquallySpacedSlot(x, y, from, to, numberOfPoints) {
        let xLength = x.length;
        let step = (to - from) / Number(numberOfPoints - 1);
        let halfStep = step / MLINDEX_BYTES_NUM_2;
        let lastStep = x[x.length - 1] - x[x.length - MLINDEX_BYTES_NUM_2];
        let start = from - halfStep;
        let output = Array(numberOfPoints).fill(0);
        // Init main variables
        let min = start;
        let max = start + step;
        let previousX = -Number.MAX_VALUE;
        let previousY = 0;
        let nextX = x[0];
        let nextY = y[0];
        let frontOutsideSpectra = 0;
        let backOutsideSpectra = true;
        let currentValue = 0;
        // for slot algorithm
        let currentPoints = 0;
        let i = 1; // index of input
        let j = 0; // index of output
        let mainWhile = true;
        main: while (mainWhile) {
            if (previousX >= nextX) {
                throw new Error('x must be an increasing serie');
            }
            while (previousX - Number(max) > 0) {
                if (backOutsideSpectra) {
                    currentPoints += 1;
                    backOutsideSpectra = false;
                }
                output[j] = currentPoints <= 0 ? 0 : currentValue / currentPoints;
                j += 1;
                if (j === numberOfPoints) {
                    break main;
                }
                min = max;
                max += step;
                currentValue = 0;
                currentPoints = 0;
            }
            if (previousX > Number(min)) {
                currentValue += previousY;
                currentPoints += 1;
            }
            if (previousX === -Number.MAX_VALUE || frontOutsideSpectra > 1) {
                currentPoints -= 1;
            }
            previousX = nextX;
            previousY = nextY;
            if (i < xLength) {
                nextX = x[i];
                nextY = y[i];
                i += 1;
            }
            else {
                nextX += lastStep;
                nextY = 0;
                frontOutsideSpectra += 1;
            }
        }
        return output;
    }
    integral(x0, x1, slope, intercept) {
        return Number(MLINDEX_BYTES_NUM_05 * slope * x1 * x1 + intercept * x1 - MLINDEX_BYTES_NUM_05 * slope * x0 * x0 + intercept * x0);
    }
}
let mlArrayUtilsGetEquallySpaced = new MlArrayUtilsGetEquallySpacedCls();
// ml-array-utils snv.js
class MlArrayUtilsSnvCls {
    snv(data) {
        let mean = mlStatArray.mean(data);
        let std = mlStatArray.standardDeviation(data);
        let result = [...data];
        for (let i = 0; i < data.length; i++) {
            result[i] = Number((Number(result[i]) - mean) / std);
        }
        return result;
    }
}
let mlArrayUtilsSnv = new MlArrayUtilsSnvCls();
// ml-matrix src/util.js
class MlMatrixUtilCls {
    checkRowIndex(matrix, index, outer) {
        let max = outer ? matrix.rows : matrix.rows - 1;
        if (index < 0 || index > max) {
            throw new RangeError('Row index out of range');
        }
    }
    checkColumnIndex(matrix, index, outer) {
        let max = outer ? matrix.columns : matrix.columns - 1;
        if (index < 0 || index > max) {
            throw new RangeError('Column index out of range');
        }
    }
    checkRowVector(matrix, vector) {
        if (vector instanceof Matrix) {
            return vector.to1dArray();
        }
        if (Array.isArray(vector)) {
            if (vector.length !== matrix.columns) {
                throw new Error('vector size must be the same as the number of columns');
            }
        }
        return vector;
    }
    checkColumnVector(matrix, vector) {
        if (vector instanceof Matrix) {
            return vector.to1dArray();
        }
        if (Array.isArray(vector)) {
            if (vector.length !== matrix.rows) {
                throw new RangeError('vector size must be the same as the number of rows');
            }
        }
        return vector;
    }
    checkIndices(matrix, rowIndices, columnIndices) {
        let rowOut = rowIndices.some(r => {
            return r < 0 || r >= matrix.rows;
        });
        let columnOut = columnIndices.some(c => {
            return c < 0 || c >= matrix.columns;
        });
        if (rowOut || columnOut) {
            throw new RangeError('Indices are out of range');
        }
        return [rowIndices, columnIndices];
    }
    checkRange(matrix, startRow, endRow, startColumn, endColumn) {
        if (matrix === null || startRow === null || endRow === null || startColumn === null || endColumn === null) {
            throw new RangeError('Invalid argument type');
        }
    }
    getRange(from, to) {
        let arr = Array(to - from + 1).fill(0);
        for (let i = 0; i < arr.length; i++) {
            arr[i] = from + i;
        }
        return arr;
    }
    sumByRow(matrix) {
        let sum = Matrix.zeros(matrix.rows, 1);
        for (let i = 0; i < matrix.rows; ++i) {
            for (let j = 0; j < matrix.columns; ++j) {
                sum.set(i, 0, sum.get(i, 0) + matrix.get(i, j));
            }
        }
        return sum;
    }
    sumByColumn(matrix) {
        let sum = Matrix.zeros(1, matrix.columns);
        for (let i = 0; i < matrix.rows; ++i) {
            for (let j = 0; j < matrix.columns; ++j) {
                sum.set(0, j, sum.get(0, j) + matrix.get(i, j));
            }
        }
        return sum;
    }
    sumAll(matrix) {
        let v = 0;
        for (let i = 0; i < matrix.rows; i++) {
            for (let j = 0; j < matrix.columns; j++) {
                v += matrix.get(i, j);
            }
        }
        return v;
    }
}
let mlMatrixUtil = new MlMatrixUtilCls();
// ml-matrix src/dc/util.js
class MlMatrixDcuTilCls {
    hypotenuse(a, b) {
        let r;
        if (Math.abs(a) > Math.abs(b)) {
            r = b / a;
            return Math.abs(a) * Math.sqrt(1 + r * r);
        }
        if (b !== 0) {
            r = a / b;
            return Math.abs(b) * Math.sqrt(1 + r * r);
        }
        return 0;
    }
    // For use in the decomposition algorithms. With big matrices, access time is
    // too long on elements from array subclass
    // todo check when it is fixed in v8
    // http://jsperf.com/access-and-write-array-subclass
    getEmpty2dArray(rows, columns) {
        let array = Array(rows).fill([0.0]);
        for (let i = 0; i < rows; i++) {
            array[i] = Array(columns).fill(0.0);
        }
        return array;
    }
    getFilled2dArray(rows, columns, value) {
        let array = Array(rows).fill([0.0]);
        for (let i = 0; i < rows; i++) {
            array[i] = Array(columns).fill(0.0);
            for (let j = 0; j < columns; j++) {
                array[i][j] = value;
            }
        }
        return array;
    }
}
let mlMatrixDcuTil = new MlMatrixDcuTilCls();
// ml-matrix src/dc/lu.js
class MlMatrixDclu {
    constructor(matrix) {
        this.pivotVector = [];
        this.pivotSign = 0.0;
        let newMatrix = matrix;
        newMatrix = Matrix.checkMatrix(matrix);
        this.matrix = newMatrix;
        let lu = newMatrix.clone();
        let rows = lu.rows;
        let columns = lu.columns;
        let pivotVector = Array(rows).fill(0);
        let pivotSign = 1.0;
        let p;
        let s;
        let t;
        let v;
        let luRowi;
        let luColj;
        let kmax;
        for (let i = 0; i < rows; i++) {
            pivotVector[i] = i;
        }
        luColj = Array(rows).fill(0);
        for (let j = 0; j < columns; j++) {
            for (let i = 0; i < rows; i++) {
                luColj[i] = lu.get(i, j);
            }
            for (let i = 0; i < rows; i++) {
                luRowi = lu.getRow(i);
                kmax = Math.min(i, j);
                s = 0;
                for (let k = 0; k < kmax; k++) {
                    s += luRowi[k] * luColj[k];
                }
                luColj[i] = luColj[i] - s;
                luRowi[j] = luColj[i];
            }
            p = j;
            for (let i = j + 1; i < rows; i++) {
                if (Math.abs(luColj[i]) > Math.abs(luColj[p])) {
                    p = i;
                }
            }
            if (p !== j) {
                for (let k = 0; k < columns; k++) {
                    t = lu.get(p, k);
                    lu.set(p, k, lu.get(j, k));
                    lu.set(j, k, t);
                }
                v = pivotVector[p];
                pivotVector[p] = pivotVector[j];
                pivotVector[j] = v;
                pivotSign = -pivotSign;
            }
            if (j < rows && lu.get(j, j) !== 0) {
                for (let i = j + 1; i < rows; i++) {
                    lu.set(i, j, lu.get(i, j) / lu.get(j, j));
                }
            }
        }
        this.lu = lu;
        this.pivotVector = pivotVector;
        this.pivotSign = pivotSign;
    }
    isSingular() {
        let data = this.lu;
        let col = data.columns;
        for (let j = 0; j < col; j++) {
            if (data.get(j, j) === 0) {
                return true;
            }
        }
        return false;
    }
    determinant() {
        let data = this.lu;
        if (!data.isSquare()) {
            throw new Error('Matrix must be square');
        }
        let determinant = this.pivotSign;
        let col = data.columns;
        for (let j = 0; j < col; j++) {
            determinant *= data.get(j, j);
        }
        return determinant;
    }
    lowerTriangularMatrix() {
        let data = this.lu;
        let rows = data.rows;
        let columns = data.columns;
        let x = new Matrix(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                if (i > j) {
                    x.set(i, j, data.get(i, j));
                }
                else if (i === j) {
                    x.set(i, j, 1);
                }
                else {
                    x.set(i, j, 0);
                }
            }
        }
        return x;
    }
    upperTriangularMatrix() {
        let data = this.lu;
        let rows = data.rows;
        let columns = data.columns;
        let x = new Matrix(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                if (i <= j) {
                    x.set(i, j, data.get(i, j));
                }
                else {
                    x.set(i, j, 0);
                }
            }
        }
        return x;
    }
    pivotPermutationVector() {
        return [...this.pivotVector];
    }
    solve(value) {
        value = Matrix.checkMatrix(value);
        let lu = this.lu;
        let rows = lu.rows;
        if (rows !== value.rows) {
            throw new Error('Invalid matrix dimensions');
        }
        if (this.isSingular()) {
            throw new Error('LU matrix is singular');
        }
        let count = value.columns;
        let x = value.subMatrixRow(this.pivotVector, 0, count - 1);
        let columns = lu.columns;
        for (let k = 0; k < columns; k++) {
            for (let i = k + 1; i < columns; i++) {
                for (let j = 0; j < count; j++) {
                    x.set(i, j, x.get(i, j) - x.get(k, j) * lu.get(i, k));
                }
            }
        }
        for (let k = columns - 1; k >= 0; k--) {
            for (let j = 0; j < count; j++) {
                x.set(k, j, x.get(k, j) / lu.get(k, k));
            }
            for (let i = 0; i < k; i++) {
                for (let j = 0; j < count; j++) {
                    x.set(i, j, x.get(i, j) - x.get(k, j) * lu.get(i, k));
                }
            }
        }
        return x;
    }
}
// ml-matrix src/dc/svd.js
class MlMatrixDcsvd {
    constructor(value, options) {
        this.m = 0;
        this.n = 0;
        this.s = [];
        value = Matrix.checkMatrix(value);
        let m = value.rows;
        let n = value.columns;
        let nu = Math.min(m, n);
        let wantu = true;
        let wantv = true;
        if (options.computeLeftSingularVectors === false) {
            wantu = false;
        }
        if (options.computeRightSingularVectors === false) {
            wantv = false;
        }
        let autoTranspose = options.autoTranspose === true;
        let swapped = false;
        let a;
        if (m < n) {
            if (!autoTranspose) {
                a = value.clone();
                // eslint-disable-next-line no-console
                console.log('Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose');
            }
            else {
                a = value.transpose();
                m = a.rows;
                n = a.columns;
                swapped = true;
                let aux = wantu;
                wantu = wantv;
                wantv = aux;
            }
        }
        else {
            a = value.clone();
        }
        let s = Array(Math.min(m + 1, n)).fill(0.0);
        let u = mlMatrixDcuTil.getFilled2dArray(m, nu, 0);
        let v = mlMatrixDcuTil.getFilled2dArray(n, n, 0);
        let e = Array(n).fill(0.0);
        let work = Array(m).fill(0.0);
        let nct = Math.min(m - 1, n);
        let nrt = Math.max(0, Math.min(n - MLINDEX_BYTES_NUM_2, m));
        let p;
        let t;
        let f;
        let cs;
        let sn;
        let kase;
        let scale;
        let sp;
        let spm1;
        let epm1;
        let sk;
        let ek;
        let b;
        let c;
        let shift;
        let g;
        for (let k = 0; k < Math.max(nct, nrt); k++) {
            if (k < nct) {
                s[k] = 0;
                for (let i = k; i < m; i++) {
                    s[k] = mlMatrixDcuTil.hypotenuse(s[k], a.get(i, k));
                }
                if (s[k] !== 0) {
                    if (a.get(k, k) < 0) {
                        s[k] = -s[k];
                    }
                    for (let i = k; i < m; i++) {
                        a.set(i, k, a.get(i, k) / s[k]);
                    }
                    a.set(k, k, a.get(k, k) + 1);
                }
                s[k] = -s[k];
            }
            for (let j = k + 1; j < n; j++) {
                if (k < nct && s[k] !== 0) {
                    t = 0;
                    for (let i = k; i < m; i++) {
                        t += a.get(i, k) * a.get(i, j);
                    }
                    t = -t / a.get(k, k);
                    for (let i = k; i < m; i++) {
                        a.set(i, j, a.get(i, j) + t * a.get(i, k));
                    }
                }
                e[j] = a.get(k, j);
            }
            if (wantu && k < nct) {
                for (let i = k; i < m; i++) {
                    u[i][k] = a.get(i, k);
                }
            }
            if (k < nrt) {
                e[k] = 0;
                for (let i = k + 1; i < n; i++) {
                    e[k] = mlMatrixDcuTil.hypotenuse(e[k], e[i]);
                }
                if (e[k] !== 0) {
                    if (e[k + 1] < 0) {
                        e[k] = 0 - e[k];
                    }
                    for (let i = k + 1; i < n; i++) {
                        e[i] /= e[k];
                    }
                    e[k + 1] += 1;
                }
                e[k] = -e[k];
                if (k + 1 < m && e[k] !== 0) {
                    for (let i = k + 1; i < m; i++) {
                        work[i] = 0.0;
                    }
                    for (let j = k + 1; j < n; j++) {
                        for (let i = k + 1; i < m; i++) {
                            work[i] += e[j] * a.get(i, j);
                        }
                    }
                    for (let j = k + 1; j < n; j++) {
                        t = -e[j] / e[k + 1];
                        for (let i = k + 1; i < m; i++) {
                            a.set(i, j, a.get(i, j) + t * work[i]);
                        }
                    }
                }
                if (wantv) {
                    for (let i = k + 1; i < n; i++) {
                        v[i][k] = e[i];
                    }
                }
            }
        }
        p = Math.min(n, m + 1);
        if (nct < n) {
            s[nct] = a.get(nct, nct);
        }
        if (m < p) {
            s[p - 1] = 0;
        }
        if (nrt + 1 < p) {
            e[nrt] = a.get(nrt, p - 1);
        }
        e[p - 1] = 0;
        if (wantu) {
            for (let j = nct; j < nu; j++) {
                for (let i = 0; i < m; i++) {
                    u[i][j] = 0;
                }
                u[j][j] = 1;
            }
            for (let k = nct - 1; k >= 0; k--) {
                if (s[k] !== 0) {
                    for (let j = k + 1; j < nu; j++) {
                        t = 0;
                        for (let i = k; i < m; i++) {
                            t += u[i][k] * u[i][j];
                        }
                        t = -t / u[k][k];
                        for (let i = k; i < m; i++) {
                            u[i][j] += t * u[i][k];
                        }
                    }
                    for (let i = k; i < m; i++) {
                        u[i][k] = -Number(u[i][k]);
                    }
                    u[k][k] = 1 + u[k][k];
                    for (let i = 0; i < k - 1; i++) {
                        u[i][k] = 0;
                    }
                }
                else {
                    for (let i = 0; i < m; i++) {
                        u[i][k] = 0;
                    }
                    u[k][k] = 1;
                }
            }
        }
        if (wantv) {
            for (let k = n - 1; k >= 0; k--) {
                if (k < nrt && e[k] !== 0) {
                    for (let j = k + 1; j < n; j++) {
                        t = 0;
                        for (let i = k + 1; i < n; i++) {
                            t += v[i][k] * v[i][j];
                        }
                        t = -t / v[k + 1][k];
                        for (let i = k + 1; i < n; i++) {
                            v[i][j] += t * v[i][k];
                        }
                    }
                }
                for (let i = 0; i < n; i++) {
                    v[i][k] = 0;
                }
                v[k][k] = 1;
            }
        }
        let pp = p - 1;
        let iter = 0;
        let eps = Math.pow(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_52);
        while (p > 0) {
            let k = p - MLINDEX_BYTES_NUM_2;
            for (k; k >= -1; k--) {
                if (k === -1) {
                    break;
                }
                if (Math.abs(e[k]) <= eps * (Math.abs(s[k]) + Math.abs(s[k + 1]))) {
                    e[k] = 0;
                    break;
                }
            }
            if (k === p - MLINDEX_BYTES_NUM_2) {
                kase = MLINDEX_BYTES_NUM_4;
            }
            else {
                let ks = p - 1;
                for (ks; ks >= k; ks--) {
                    if (ks === k) {
                        break;
                    }
                    t = (ks !== p ? Math.abs(e[ks]) : 0) + (ks !== k + 1 ? Math.abs(e[ks - 1]) : 0);
                    if (Math.abs(s[ks]) <= eps * t) {
                        s[ks] = 0;
                        break;
                    }
                }
                if (ks === k) {
                    kase = MLINDEX_BYTES_NUM_3;
                }
                else if (ks === p - 1) {
                    kase = 1;
                }
                else {
                    kase = MLINDEX_BYTES_NUM_2;
                    k = ks;
                }
            }
            k += 1;
            switch (kase) {
                case 1: {
                    f = e[p - MLINDEX_BYTES_NUM_2];
                    e[p - MLINDEX_BYTES_NUM_2] = 0;
                    for (let j = p - MLINDEX_BYTES_NUM_2; j >= k; j--) {
                        t = mlMatrixDcuTil.hypotenuse(s[j], f);
                        cs = s[j] / t;
                        sn = f / t;
                        s[j] = t;
                        if (j !== k) {
                            f = -sn * e[j - 1];
                            e[j - 1] = cs * e[j - 1];
                        }
                        if (wantv) {
                            for (let i = 0; i < n; i++) {
                                t = cs * v[i][j] + sn * v[i][p - 1];
                                v[i][p - 1] = -sn * v[i][j] + cs * v[i][p - 1];
                                v[i][j] = t;
                            }
                        }
                    }
                    break;
                }
                case MLINDEX_BYTES_NUM_2: {
                    f = e[k - 1];
                    e[k - 1] = 0;
                    for (let j = k; j < p; j++) {
                        t = mlMatrixDcuTil.hypotenuse(s[j], f);
                        cs = s[j] / t;
                        sn = f / t;
                        s[j] = t;
                        f = -sn * e[j];
                        e[j] = cs * e[j];
                        if (wantu) {
                            for (let i = 0; i < m; i++) {
                                t = cs * u[i][j] + sn * u[i][k - 1];
                                u[i][k - 1] = -sn * u[i][j] + cs * u[i][k - 1];
                                u[i][j] = t;
                            }
                        }
                    }
                    break;
                }
                case MLINDEX_BYTES_NUM_3: {
                    scale = Math.max(Math.max(Math.max(Math.max(Math.abs(s[p - 1]), Math.abs(s[p - MLINDEX_BYTES_NUM_2])), Math.abs(e[p - MLINDEX_BYTES_NUM_2])), Math.abs(s[k])), Math.abs(e[k]));
                    sp = s[p - 1] / scale;
                    spm1 = s[p - MLINDEX_BYTES_NUM_2] / scale;
                    epm1 = e[p - MLINDEX_BYTES_NUM_2] / scale;
                    sk = s[k] / scale;
                    ek = e[k] / scale;
                    b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / MLINDEX_BYTES_NUM_2;
                    c = sp * epm1 * (sp * epm1);
                    shift = 0;
                    if (b !== 0 || c !== 0) {
                        shift = Math.sqrt(b * b + c);
                        if (b < 0) {
                            shift = -shift;
                        }
                        shift = c / (b + shift);
                    }
                    f = (sk + sp) * (sk - sp) + shift;
                    g = sk * ek;
                    for (let j = k; j < p - 1; j++) {
                        t = mlMatrixDcuTil.hypotenuse(f, g);
                        cs = f / t;
                        sn = g / t;
                        if (j !== k) {
                            e[j - 1] = t;
                        }
                        f = cs * s[j] + sn * e[j];
                        e[j] = cs * e[j] - sn * s[j];
                        g = sn * s[j + 1];
                        s[j + 1] = cs * s[j + 1];
                        if (wantv) {
                            for (let i = 0; i < n; i++) {
                                t = cs * v[i][j] + sn * v[i][j + 1];
                                v[i][j + 1] = -sn * v[i][j] + cs * v[i][j + 1];
                                v[i][j] = t;
                            }
                        }
                        t = mlMatrixDcuTil.hypotenuse(f, g);
                        cs = f / t;
                        sn = g / t;
                        s[j] = t;
                        f = cs * e[j] + sn * s[j + 1];
                        s[j + 1] = -sn * e[j] + cs * s[j + 1];
                        g = sn * e[j + 1];
                        e[j + 1] = cs * e[j + 1];
                        if (wantu && j < m - 1) {
                            for (let i = 0; i < m; i++) {
                                t = cs * u[i][j] + sn * u[i][j + 1];
                                u[i][j + 1] = -sn * u[i][j] + cs * u[i][j + 1];
                                u[i][j] = t;
                            }
                        }
                    }
                    e[p - MLINDEX_BYTES_NUM_2] = f;
                    iter = iter + 1;
                    break;
                }
                case MLINDEX_BYTES_NUM_4: {
                    if (s[k] <= 0) {
                        s[k] = s[k] < 0 ? -s[k] : 0;
                        if (wantv) {
                            for (let i = 0; i <= pp; i++) {
                                v[i][k] = -v[i][k];
                            }
                        }
                    }
                    while (k < pp) {
                        if (s[k] >= s[k + 1]) {
                            break;
                        }
                        t = s[k];
                        s[k] = s[k + 1];
                        s[k + 1] = t;
                        if (wantv && k < n - 1) {
                            for (let i = 0; i < n; i++) {
                                t = v[i][k + 1];
                                v[i][k + 1] = v[i][k];
                                v[i][k] = t;
                            }
                        }
                        if (wantu && k < m - 1) {
                            for (let i = 0; i < m; i++) {
                                t = u[i][k + 1];
                                u[i][k + 1] = u[i][k];
                                u[i][k] = t;
                            }
                        }
                        k += 1;
                    }
                    iter = 0;
                    p -= 1;
                    break;
                }
                default:
                    break;
            }
        }
        if (swapped) {
            let tmp = v;
            v = u;
            u = tmp;
        }
        this.m = m;
        this.n = n;
        this.s = s;
        this.u = u;
        this.v = v;
    }
    condition() {
        return this.s[0] / this.s[Math.min(this.m, this.n) - 1];
    }
    norm2() {
        return this.s[0];
    }
    rank() {
        let eps = Math.pow(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_52);
        let tol = Math.max(this.m, this.n) * this.s[0] * eps;
        let r = 0.0;
        let s = this.s;
        for (let i = 0, ii = s.length; i < ii; i++) {
            if (s[i] > tol) {
                r += 1;
            }
        }
        return r;
    }
    diagonal() {
        return this.s;
    }
    threshold() {
        return (Math.pow(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_52) / MLINDEX_BYTES_NUM_2) * Math.max(this.m, this.n) * this.s[0];
    }
    leftSingularVectors() {
        if (!Matrix.isMatrix(this.u)) {
            return new Matrix(this.u);
        }
        return this.u;
    }
    rightSingularVectors() {
        if (!Matrix.isMatrix(this.v)) {
            return new Matrix(this.v);
        }
        return this.v;
    }
    diagonalMatrix() {
        return Matrix.diag(this.s);
    }
    solve(value) {
        let y = value;
        let e = this.threshold;
        let scols = this.s.length;
        let ls = Matrix.zeros(scols, scols);
        for (let i = 0; i < scols; i++) {
            if (Math.abs(this.s[i]) <= Number(e)) {
                ls.set(i, i, 0);
            }
            else {
                ls.set(i, i, 1 / this.s[i]);
            }
        }
        let u = this.u;
        let v = this.rightSingularVectors();
        let vl = v.mmul(ls);
        let vRows = v.rows;
        let uRows = u.length;
        let vlu = Matrix.zeros(vRows, uRows);
        let sum;
        for (let i = 0; i < vRows; i++) {
            for (let j = 0; j < uRows; j++) {
                sum = 0;
                for (let k = 0; k < scols; k++) {
                    sum += vl.get(i, k) * u[j][k];
                }
                vlu.set(i, j, sum);
            }
        }
        return vlu.mmul(y);
    }
    solveForDiagonal(value) {
        return this.solve(Matrix.diag(value));
    }
    inverse() {
        let v = this.v;
        let e = this.threshold();
        let vRows = v.length;
        let vCols = v[0].length;
        let x = new Matrix(vRows, this.s.length);
        for (let i = 0; i < vRows; i++) {
            for (let j = 0; j < vCols; j++) {
                if (Math.abs(this.s[j]) > Number(e)) {
                    x.set(i, j, Number(v[i]) / this.s[j]);
                }
                else {
                    x.set(i, j, 0);
                }
            }
        }
        let u = this.u;
        let uRows = u.length;
        let uCols = u[0].length;
        let y = new Matrix(vRows, uRows);
        let sum;
        for (let i = 0; i < vRows; i++) {
            for (let j = 0; j < uRows; j++) {
                sum = 0.0;
                for (let k = 0; k < uCols; k++) {
                    sum += x.get(i, k) * u[j][k];
                }
                y.set(i, j, sum);
            }
        }
        return y;
    }
}
// ml-matrix src/abstractMatrix.js
class Matrix {
    constructor(nRows, nColumns) {
        this.rows = 0;
        this.columns = 0;
        if (nRows instanceof Matrix) {
            this.array = nRows.array;
            this.rows = nRows.rows;
            this.columns = nRows.columns;
        }
        else if (typeof nRows === 'number' && nRows > 0) {
            this.array = Array(nRows).fill(0.0);
            if (nColumns !== undefined && nColumns > 0) {
                for (let i = 0; i < nRows; i++) {
                    this.array[i] = Array(nColumns).fill(0.0);
                }
                this.rows = nRows;
                this.columns = nColumns;
            }
            else {
                throw new Error('nColumns must be a positive integer');
            }
        }
        else if (nRows instanceof Array && nRows.length > 0 && nRows[0] instanceof Array) {
            this.array = nRows;
            this.rows = nRows.length;
            this.columns = nRows[0].length;
        }
        else {
            throw new Error('First argument must be a positive number or an array');
        }
    }
    set(rowIndex, columnIndex, value) {
        this.array[rowIndex][columnIndex] = value;
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.array[rowIndex][columnIndex];
    }
    clone() {
        let newMatrix = new Matrix(this.rows, this.columns);
        for (let row = 0; row < this.rows; row++) {
            for (let column = 0; column < this.columns; column++) {
                newMatrix.set(row, column, this.get(row, column));
            }
        }
        return newMatrix;
    }
    static from1DArray(newRows, newColumns, newData) {
        let length = newRows * newColumns;
        if (length !== newData.length) {
            throw new RangeError('Data length does not match given dimensions');
        }
        let newMatrix = new Matrix(newRows, newColumns);
        for (let row = 0; row < newRows; row++) {
            for (let column = 0; column < newColumns; column++) {
                newMatrix.set(row, column, newData[row * newColumns + column]);
            }
        }
        return newMatrix;
    }
    static rowVector(newData) {
        let vector = new Matrix(1, newData.length);
        for (let i = 0; i < newData.length; i++) {
            vector.set(0, i, newData[i]);
        }
        return vector;
    }
    static columnVector(newData) {
        let vector = new Matrix(newData.length, 1);
        for (let i = 0; i < newData.length; i++) {
            vector.set(i, 0, newData[i]);
        }
        return vector;
    }
    static empty(rows, columns) {
        return new Matrix(rows, columns);
    }
    static zeros(rows, columns) {
        return Matrix.empty(rows, columns).fill(0.0);
    }
    static ones(rows, columns) {
        return Matrix.empty(rows, columns).fill(1.0);
    }
    static rand(rows, columns, rng) {
        rng !== null && rng !== void 0 ? rng : Math.random();
        let matrix = Matrix.empty(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                matrix.set(i, j, Math.random());
            }
        }
        return matrix;
    }
    static randInt(rows, columns, maxValue, rng) {
        let maxV = maxValue !== null && maxValue !== void 0 ? maxValue : MLINDEX_BYTES_NUM_1000;
        let matrix = Matrix.empty(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                let value = Math.floor(Math.random() * maxV);
                matrix.set(i, j, value);
            }
        }
        return matrix;
    }
    static eye(rows, columns, value) {
        let newColumns = columns;
        let newValue = value;
        if (columns === undefined) {
            newColumns = rows;
        }
        if (value === undefined) {
            newValue = 1;
        }
        let min = Math.min(rows, newColumns);
        let matrix = Matrix.zeros(rows, newColumns);
        for (let i = 0; i < min; i++) {
            matrix.set(i, i, newValue);
        }
        return matrix;
    }
    static diag(data, rows, columns) {
        let newRows = rows;
        let newColumns = columns;
        let l = data.length;
        if (rows === undefined) {
            newRows = l;
        }
        if (columns === undefined) {
            newColumns = rows;
        }
        let min = Math.min(l, newRows, newColumns);
        let matrix = Matrix.zeros(newRows, newColumns);
        for (let i = 0; i < min; i++) {
            matrix.set(i, i, data[i]);
        }
        return matrix;
    }
    static min(matrix1, matrix2) {
        let matrix11 = Matrix.checkMatrix(matrix1);
        let matrix22 = Matrix.checkMatrix(matrix2);
        let rows = matrix11.rows;
        let columns = matrix11.columns;
        let result = new Matrix(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                result.set(i, j, Math.min(matrix11.get(i, j), matrix22.get(i, j)));
            }
        }
        return result;
    }
    static max(matrix1, matrix2) {
        let matrix11 = Matrix.checkMatrix(matrix1);
        let matrix22 = Matrix.checkMatrix(matrix2);
        let rows = matrix11.rows;
        let columns = matrix11.columns;
        let result = new Matrix(rows, columns);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < columns; j++) {
                result.set(i, j, Math.max(matrix11.get(i, j), matrix22.get(i, j)));
            }
        }
        return result;
    }
    static checkMatrix(value) {
        return Matrix.isMatrix(value) ? value : new Matrix(value);
    }
    static isMatrix(value) {
        return value !== null && value instanceof Matrix;
    }
    size() {
        return this.rows * this.columns;
    }
    apply(callback) {
        let ii = this.rows;
        let jj = this.columns;
        for (let i = 0; i < ii; i++) {
            for (let j = 0; j < jj; j++) {
                callback(this, i, j);
            }
        }
        return this;
    }
    to1dArray() {
        let array = Array(this.size()).fill(0.0);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                array[i * this.columns + j] = this.get(i, j);
            }
        }
        return array;
    }
    to2dArray() {
        let copy = Array(this.rows).fill([0.0]);
        for (let i = 0; i < this.rows; i++) {
            copy[i] = Array(this.columns).fill(0);
            for (let j = 0; j < this.columns; j++) {
                copy[i][j] = this.get(i, j);
            }
        }
        return copy;
    }
    isRowVector() {
        return this.rows === 1;
    }
    isColumnVector() {
        return this.columns === 1;
    }
    isVector() {
        return this.rows === 1 || this.columns === 1;
    }
    isSquare() {
        return this.rows === this.columns;
    }
    isSymmetric() {
        if (this.isSquare()) {
            for (let i = 0; i < this.rows; i++) {
                for (let j = 0; j <= i; j++) {
                    if (this.get(i, j) !== this.get(j, i)) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }
    repeat(rowRep, colRep) {
        let newRowRep = rowRep > 0 ? rowRep : 1;
        let newColRep = colRep > 0 ? colRep : 1;
        let matrix = new Matrix(this.rows * newRowRep, this.columns * newColRep);
        for (let i = 0; i < newRowRep; i++) {
            for (let j = 0; j < newColRep; j++) {
                matrix.setSubMatrix(this, this.rows * i, this.columns * j);
            }
        }
        return matrix;
    }
    fill(value) {
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, value);
            }
        }
        return this;
    }
    neg() {
        return this.mulS(-1);
    }
    getRow(index) {
        mlMatrixUtil.checkRowIndex(this, index, false);
        let row = Array(this.columns).fill(0.0);
        for (let i = 0; i < this.columns; i++) {
            row[i] = this.get(index, i);
        }
        return row;
    }
    getRowVector(index) {
        return Matrix.rowVector(this.getRow(index));
    }
    setRow(index, array) {
        mlMatrixUtil.checkRowIndex(this, index, false);
        for (let i = 0; i < this.columns; i++) {
            this.set(index, i, array.get(i, i));
        }
        return this;
    }
    swapRows(row1, row2) {
        mlMatrixUtil.checkRowIndex(this, row1, false);
        mlMatrixUtil.checkRowIndex(this, row2, false);
        for (let i = 0; i < this.columns; i++) {
            let temp = this.get(row1, i);
            this.set(row1, i, this.get(row2, i));
            this.set(row2, i, temp);
        }
        return this;
    }
    getColumn(index) {
        mlMatrixUtil.checkColumnIndex(this, index, false);
        let column = Array(this.rows).fill(0.0);
        for (let i = 0; i < this.rows; i++) {
            column[i] = this.get(i, index);
        }
        return column;
    }
    getColumnVector(index) {
        return Matrix.columnVector(this.getColumn(index));
    }
    setColumn(index, array) {
        mlMatrixUtil.checkColumnIndex(this, index, false);
        for (let i = 0; i < this.rows; i++) {
            this.set(i, index, array[i]);
        }
        return this;
    }
    swapColumns(column1, column2) {
        mlMatrixUtil.checkColumnIndex(this, column1, false);
        mlMatrixUtil.checkColumnIndex(this, column2, false);
        for (let i = 0; i < this.rows; i++) {
            let temp = this.get(i, column1);
            this.set(i, column1, this.get(i, column2));
            this.set(i, column2, temp);
        }
        return this;
    }
    addRowVector(vector) {
        let newVector = mlMatrixUtil.checkRowVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) + Number(newVector[j]));
            }
        }
        return this;
    }
    subRowVector(vector) {
        let newVector = mlMatrixUtil.checkRowVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) - newVector[j]);
            }
        }
        return this;
    }
    mulRowVector(vector) {
        let newVector = mlMatrixUtil.checkRowVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) * newVector[j]);
            }
        }
        return this;
    }
    divRowVector(vector) {
        let newVector = mlMatrixUtil.checkRowVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) / newVector[j]);
            }
        }
        return this;
    }
    addColumnVector(vector) {
        let newVector = mlMatrixUtil.checkRowVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) + newVector[i]);
            }
        }
        return this;
    }
    subColumnVector(vector) {
        let newVector = mlMatrixUtil.checkColumnVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) - newVector[i]);
            }
        }
        return this;
    }
    mulColumnVector(vector) {
        let newVector = mlMatrixUtil.checkColumnVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) * newVector[i]);
            }
        }
        return this;
    }
    divColumnVector(vector) {
        let newVector = mlMatrixUtil.checkColumnVector(this, vector);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) / Number(newVector[i]));
            }
        }
        return this;
    }
    mulRow(index, value) {
        mlMatrixUtil.checkRowIndex(this, index, false);
        for (let i = 0; i < this.columns; i++) {
            this.set(index, i, this.get(index, i) * value);
        }
        return this;
    }
    mulColumn(index, value) {
        mlMatrixUtil.checkColumnIndex(this, index, false);
        for (let i = 0; i < this.rows; i++) {
            this.set(i, index, this.get(i, index) * value);
        }
        return this;
    }
    max() {
        let v = this.get(0, 0);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                if (this.get(i, j) > v) {
                    v = this.get(i, j);
                }
            }
        }
        return v;
    }
    maxIndex() {
        let v = this.get(0, 0);
        let idx = [0, 0];
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                if (this.get(i, j) > v) {
                    v = this.get(i, j);
                    idx[0] = i;
                    idx[1] = j;
                }
            }
        }
        return idx;
    }
    min() {
        let v = this.get(0, 0);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                if (this.get(i, j) < v) {
                    v = this.get(i, j);
                }
            }
        }
        return v;
    }
    minIndex() {
        let v = this.get(0, 0);
        let idx = [0, 0];
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                if (this.get(i, j) < v) {
                    v = this.get(i, j);
                    idx[0] = i;
                    idx[1] = j;
                }
            }
        }
        return idx;
    }
    maxRow(row) {
        mlMatrixUtil.checkRowIndex(this, row, false);
        let v = this.get(row, 0);
        for (let i = 1; i < this.columns; i++) {
            if (this.get(row, i) > v) {
                v = this.get(row, i);
            }
        }
        return v;
    }
    maxRowIndex(row) {
        mlMatrixUtil.checkRowIndex(this, row, false);
        let v = this.get(row, 0);
        let idx = [row, 0];
        for (let i = 1; i < this.columns; i++) {
            if (this.get(row, i) > v) {
                v = this.get(row, i);
                idx[1] = i;
            }
        }
        return idx;
    }
    minRow(row) {
        mlMatrixUtil.checkRowIndex(this, row, false);
        let v = this.get(row, 0);
        for (let i = 1; i < this.columns; i++) {
            if (this.get(row, i) < v) {
                v = this.get(row, i);
            }
        }
        return v;
    }
    minRowIndex(row) {
        mlMatrixUtil.checkRowIndex(this, row, false);
        let v = this.get(row, 0);
        let idx = [row, 0];
        for (let i = 1; i < this.columns; i++) {
            if (this.get(row, i) < v) {
                v = this.get(row, i);
                idx[1] = i;
            }
        }
        return idx;
    }
    maxColumn(column) {
        mlMatrixUtil.checkColumnIndex(this, column, false);
        let v = this.get(0, column);
        for (let i = 1; i < this.rows; i++) {
            if (this.get(i, column) > v) {
                v = this.get(i, column);
            }
        }
        return v;
    }
    maxColumnIndex(column) {
        mlMatrixUtil.checkColumnIndex(this, column, false);
        let v = this.get(0, column);
        let idx = [0, column];
        for (let i = 1; i < this.rows; i++) {
            if (this.get(i, column) > v) {
                v = this.get(i, column);
                idx[0] = i;
            }
        }
        return idx;
    }
    minColumn(column) {
        mlMatrixUtil.checkColumnIndex(this, column, false);
        let v = this.get(0, column);
        for (let i = 1; i < this.rows; i++) {
            if (this.get(i, column) < v) {
                v = this.get(i, column);
            }
        }
        return v;
    }
    minColumnIndex(column) {
        mlMatrixUtil.checkColumnIndex(this, column, false);
        let v = this.get(0, column);
        let idx = [0, column];
        for (let i = 1; i < this.rows; i++) {
            if (this.get(i, column) < v) {
                v = this.get(i, column);
                idx[0] = i;
            }
        }
        return idx;
    }
    diag() {
        let min = Math.min(this.rows, this.columns);
        let diag = Array(min).fill(0.0);
        for (let i = 0; i < min; i++) {
            diag[i] = this.get(i, i);
        }
        return diag;
    }
    sum(by) {
        switch (by) {
            case 'row':
                return mlMatrixUtil.sumByRow(this);
            case 'column':
                return mlMatrixUtil.sumByColumn(this);
            default:
                return mlMatrixUtil.sumAll(this);
        }
    }
    mean() {
        return this.sum('') / Number(this.size);
    }
    prod() {
        let prod = 1.0;
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                prod *= this.get(i, j);
            }
        }
        return prod;
    }
    cumulativeSum() {
        let sum = 0.0;
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                sum += this.get(i, j);
                this.set(i, j, sum);
            }
        }
        return this;
    }
    dot(vector2) {
        let vector2D1 = [];
        if (Matrix.isMatrix(vector2)) {
            vector2D1 = vector2.to1dArray();
        }
        let vector1D1 = this.to1dArray();
        if (vector1D1.length !== vector2D1.length) {
            throw new RangeError('vectors do not have the same size');
        }
        let dot = 0.0;
        for (let i = 0; i < vector1D1.length; i++) {
            dot += vector1D1[i] * vector2D1[i];
        }
        return dot;
    }
    mmul(other) {
        other = Matrix.checkMatrix(other);
        if (this.columns !== other.rows) {
            throw new RangeError('Number of columns of left matrix are not equal to number of rows of right matrix.');
        }
        let m = this.rows;
        let n = this.columns;
        let p = other.columns;
        let result = new Matrix(m, p);
        let bColj = Array(n).fill(0.0);
        for (let j = 0; j < p; j++) {
            for (let k = 0; k < n; k++) {
                bColj[k] = other.get(k, j);
            }
            for (let i = 0; i < m; i++) {
                let s = 0.0;
                for (let k = 0; k < n; k++) {
                    s += this.get(i, k) * bColj[k];
                }
                result.set(i, j, s);
            }
        }
        return result;
    }
    strassen2x2(other) {
        let result = new Matrix(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_2);
        let a11 = this.get(0, 0);
        let b11 = other.get(0, 0);
        let a12 = this.get(0, 1);
        let b12 = other.get(0, 1);
        let a21 = this.get(1, 0);
        let b21 = other.get(1, 0);
        let a22 = this.get(1, 1);
        let b22 = other.get(1, 1);
        let m1 = (a11 + a22) * (b11 + b22);
        let m2 = (a21 + a22) * b11;
        let m3 = a11 * (b12 - b22);
        let m4 = a22 * (b21 - b11);
        let m5 = (a11 + a12) * b22;
        let m6 = (a21 - a11) * (b11 + b12);
        let m7 = (a12 - a22) * (b21 + b22);
        let c00 = m1 + m4 - m5 + m7;
        let c01 = m3 + m5;
        let c10 = m2 + m4;
        let c11 = m1 - m2 + m3 + m6;
        result.set(0, 0, c00);
        result.set(0, 1, c01);
        result.set(1, 0, c10);
        result.set(1, 1, c11);
        return result;
    }
    strassen3x3(other) {
        let result = new Matrix(MLINDEX_BYTES_NUM_3, MLINDEX_BYTES_NUM_3);
        let a00 = this.get(0, 0);
        let a01 = this.get(0, 1);
        let a02 = this.get(0, MLINDEX_BYTES_NUM_2);
        let a10 = this.get(1, 0);
        let a11 = this.get(1, 1);
        let a12 = this.get(1, MLINDEX_BYTES_NUM_2);
        let a20 = this.get(MLINDEX_BYTES_NUM_2, 0);
        let a21 = this.get(MLINDEX_BYTES_NUM_2, 1);
        let a22 = this.get(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_2);
        let b00 = other.get(0, 0);
        let b01 = other.get(0, 1);
        let b02 = other.get(0, MLINDEX_BYTES_NUM_2);
        let b10 = other.get(1, 0);
        let b11 = other.get(1, 1);
        let b12 = other.get(1, MLINDEX_BYTES_NUM_2);
        let b20 = other.get(MLINDEX_BYTES_NUM_2, 0);
        let b21 = other.get(MLINDEX_BYTES_NUM_2, 1);
        let b22 = other.get(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_2);
        let m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11;
        let m2 = (a00 - a10) * (-b01 + b11);
        let m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22);
        let m4 = (-a00 + a10 + a11) * (b00 - b01 + b11);
        let m5 = (a10 + a11) * (-b00 + b01);
        let m6 = a00 * b00;
        let m7 = (-a00 + a20 + a21) * (b00 - b02 + b12);
        let m8 = (-a00 + a20) * (b02 - b12);
        let m9 = (a20 + a21) * (-b00 + b02);
        let m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12;
        let m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21);
        let m12 = (-a02 + a21 + a22) * (b11 + b20 - b21);
        let m13 = (a02 - a22) * (b11 - b21);
        let m14 = a02 * b20;
        let m15 = (a21 + a22) * (-b20 + b21);
        let m16 = (-a02 + a11 + a12) * (b12 + b20 - b22);
        let m17 = (a02 - a12) * (b12 - b22);
        let m18 = (a11 + a12) * (-b20 + b22);
        let m19 = a01 * b10;
        let m20 = a12 * b21;
        let m21 = a10 * b02;
        let m22 = a20 * b01;
        let m23 = a22 * b22;
        let c00 = m6 + m14 + m19;
        let c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15;
        let c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18;
        let c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17;
        let c11 = m2 + m4 + m5 + m6 + m20;
        let c12 = m14 + m16 + m17 + m18 + m21;
        let c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14;
        let c21 = m12 + m13 + m14 + m15 + m22;
        let c22 = m6 + m7 + m8 + m9 + m23;
        result.set(0, 0, c00);
        result.set(0, 1, c01);
        result.set(0, MLINDEX_BYTES_NUM_2, c02);
        result.set(1, 0, c10);
        result.set(1, 1, c11);
        result.set(1, MLINDEX_BYTES_NUM_2, c12);
        result.set(MLINDEX_BYTES_NUM_2, 0, c20);
        result.set(MLINDEX_BYTES_NUM_2, 1, c21);
        result.set(MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_2, c22);
        return result;
    }
    mmulStrassen(y) {
        let x = this.clone();
        let r1 = x.rows;
        let c1 = x.columns;
        let r2 = y.rows;
        let c2 = y.columns;
        if (c1 !== r2) {
            throw new RangeError(`Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.`);
        }
        let r = Math.max(r1, r2);
        let c = Math.max(c1, c2);
        x = this.embed(x, r, c);
        y = this.embed(y, r, c);
        return this.blockMult(x, y, r, c);
    }
    embed(mat, rows, cols) {
        let r = mat.rows;
        let c = mat.columns;
        if (r === rows && c === cols) {
            return mat;
        }
        else {
            let resultat = Matrix.zeros(rows, cols);
            resultat = resultat.setSubMatrix(mat, 0, 0);
            return resultat;
        }
    }
    blockMult(a, b, rows, cols) {
        let newA = a;
        let newB = b;
        if (rows <= MLINDEX_BYTES_NUM_512 || cols <= MLINDEX_BYTES_NUM_512) {
            return newA.mmul(newB);
        }
        if (rows % MLINDEX_BYTES_NUM_2 === 1 && cols % MLINDEX_BYTES_NUM_2 === 1) {
            newA = this.embed(newA, rows + 1, cols + 1);
            newB = this.embed(newB, rows + 1, cols + 1);
        }
        else if (rows % MLINDEX_BYTES_NUM_2 === 1) {
            newA = this.embed(newA, rows + 1, cols);
            newB = this.embed(newB, rows + 1, cols);
        }
        else if (cols % MLINDEX_BYTES_NUM_2 === 1) {
            newA = this.embed(newA, rows, cols + 1);
            newB = this.embed(newB, rows, cols + 1);
        }
        let halfRows = Number(newA.rows / MLINDEX_BYTES_NUM_2);
        let halfCols = Number(newA.columns / MLINDEX_BYTES_NUM_2);
        let a11 = newA.subMatrix(0, halfRows - 1, 0, halfCols - 1);
        let b11 = newA.subMatrix(0, halfRows - 1, 0, halfCols - 1);
        let a12 = newA.subMatrix(0, halfRows - 1, halfCols, newA.columns - 1);
        let b12 = newB.subMatrix(0, halfRows - 1, halfCols, newB.columns - 1);
        let a21 = newA.subMatrix(halfRows, newA.rows - 1, 0, halfCols - 1);
        let b21 = newB.subMatrix(halfRows, newB.rows - 1, 0, halfCols - 1);
        let a22 = newA.subMatrix(halfRows, newA.rows - 1, halfCols, newA.columns - 1);
        let b22 = newB.subMatrix(halfRows, newB.rows - 1, halfCols, newB.columns - 1);
        let m1 = this.blockMult(Matrix.add(a11, a22), Matrix.add(b11, b22), halfRows, halfCols);
        let m2 = this.blockMult(Matrix.add(a21, a22), b11, halfRows, halfCols);
        let m3 = this.blockMult(a11, Matrix.sub(b12, b22), halfRows, halfCols);
        let m4 = this.blockMult(a22, Matrix.sub(b21, b11), halfRows, halfCols);
        let m5 = this.blockMult(Matrix.add(a11, a12), b22, halfRows, halfCols);
        let m6 = this.blockMult(Matrix.sub(a21, a11), Matrix.add(b11, b12), halfRows, halfCols);
        let m7 = this.blockMult(Matrix.sub(a12, a22), Matrix.add(b21, b22), halfRows, halfCols);
        let c11 = Matrix.add(m1, m4);
        c11.sub(m5);
        c11.add(m7);
        let c12 = Matrix.add(m3, m5);
        let c21 = Matrix.add(m2, m4);
        let c22 = Matrix.sub(m1, m2);
        c22.add(m3);
        c22.add(m6);
        let resultat = Matrix.zeros(MLINDEX_BYTES_NUM_2 * c11.rows, MLINDEX_BYTES_NUM_2 * c11.columns);
        resultat = resultat.setSubMatrix(c11, 0, 0);
        resultat = resultat.setSubMatrix(c12, c11.rows, 0);
        resultat = resultat.setSubMatrix(c21, 0, c11.columns);
        resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns);
        return resultat.subMatrix(0, rows - 1, 0, cols - 1);
    }
    scaleRows(min, max) {
        if (min >= max) {
            throw new RangeError('min should be strictly smaller than max');
        }
        let options = new MlOptions();
        options.min = min;
        options.max = max;
        let newMatrix = new Matrix(this.rows, this.columns);
        for (let i = 0; i < this.rows; i++) {
            let scaled = mlArrayUtilsArrayUtils.scale(this.getRow(i), options);
            newMatrix.setRow(i, scaled);
        }
        return newMatrix;
    }
    scaleColumns(min, max) {
        if (min >= max) {
            throw new RangeError('min should be strictly smaller than max');
        }
        let newMatrix = Matrix.empty(this.rows, this.columns);
        let options = new MlOptions();
        options.min = min;
        options.max = max;
        for (let i = 0; i < this.columns; i++) {
            let scaled = mlArrayUtilsArrayUtils.scale(this.getColumn(i), options);
            newMatrix.setColumn(i, scaled);
        }
        return newMatrix;
    }
    kroneckerProduct(other) {
        other = Matrix.checkMatrix(other);
        let m = this.rows;
        let n = this.columns;
        let p = other.rows;
        let q = other.columns;
        let result = new Matrix(m * p, n * q);
        for (let i = 0; i < m; i++) {
            for (let j = 0; j < n; j++) {
                for (let k = 0; k < p; k++) {
                    for (let l = 0; l < q; l++) {
                        result.set(p * i + k, q * j + l, this.get(i, j) * other.get(k, l));
                    }
                }
            }
        }
        return result;
    }
    transpose() {
        let result = new Matrix(this.columns, this.rows);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                result.set(j, i, this.get(i, j));
            }
        }
        return result;
    }
    sortRows(compareFunction) {
        return this;
    }
    sortColumns(compareFunction) {
        return this;
    }
    subMatrix(startRow, endRow, startColumn, endColumn) {
        mlMatrixUtil.checkRange(this, startRow, endRow, startColumn, endColumn);
        let newMatrix = new Matrix(endRow - startRow + 1, endColumn - startColumn + 1);
        for (let i = startRow; i <= endRow; i++) {
            for (let j = startColumn; j <= endColumn; j++) {
                newMatrix.set(i - startRow, j - startColumn, this.get(i, j));
            }
        }
        return newMatrix;
    }
    subMatrixRow(indices, startColumn, endColumn) {
        let newEndColumn = endColumn;
        if (newEndColumn === undefined) {
            newEndColumn = this.columns - 1;
        }
        if (startColumn > newEndColumn || startColumn < 0 || startColumn >= this.columns || newEndColumn < 0 || newEndColumn >= this.columns) {
            throw new RangeError('Argument out of range');
        }
        let newMatrix = new Matrix(indices.length, newEndColumn - startColumn + 1);
        for (let i = 0; i < indices.length; i++) {
            for (let j = startColumn; j <= newEndColumn; j++) {
                if (indices[i] < 0 || indices[i] >= this.rows) {
                    throw new RangeError('Row index out of range: ' + indices[i]);
                }
                newMatrix.set(i, j - startColumn, this.get(indices[i], j));
            }
        }
        return newMatrix;
    }
    subMatrixColumn(indices, startRow, endRow) {
        let newEndRow = endRow;
        if (newEndRow === undefined) {
            newEndRow = this.rows - 1;
        }
        if (startRow > endRow || startRow < 0 || startRow >= this.rows || newEndRow < 0 || newEndRow >= this.rows) {
            throw new RangeError('Argument out of range');
        }
        let newMatrix = new Matrix(newEndRow - startRow + 1, indices.length);
        for (let i = 0; i < indices.length; i++) {
            for (let j = startRow; j <= newEndRow; j++) {
                if (indices[i] < 0 || indices[i] >= this.columns) {
                    throw new RangeError('Column index out of range: ' + indices[i]);
                }
                newMatrix.set(j - startRow, i, this.get(j, indices[i]));
            }
        }
        return newMatrix;
    }
    setSubMatrix(matrix, startRow, startColumn) {
        matrix = Matrix.checkMatrix(matrix);
        let endRow = startRow + matrix.rows - 1;
        let endColumn = startColumn + matrix.columns - 1;
        mlMatrixUtil.checkRange(this, startRow, endRow, startColumn, endColumn);
        for (let i = 0; i < matrix.rows; i++) {
            for (let j = 0; j < matrix.columns; j++) {
                matrix.set(startRow + i, startColumn + j, matrix.get(i, j));
            }
        }
        return this;
    }
    selection(rowIndices, columnIndices) {
        mlMatrixUtil.checkIndices(this, rowIndices, columnIndices);
        let newMatrix = new Matrix(rowIndices.length, columnIndices.length);
        return newMatrix;
    }
    trace() {
        let min = Math.min(this.rows, this.columns);
        let trace = 0.0;
        for (let i = 0; i < min; i++) {
            trace += this.get(i, i);
        }
        return trace;
    }
    transposeView() {
        return new MlMatrixTransposeView(this);
    }
    rowView(row) {
        mlMatrixUtil.checkRowIndex(this, row, false);
        return new MlMatrixRowView(this, row);
    }
    columnView(column) {
        mlMatrixUtil.checkColumnIndex(this, column, false);
        return new MlMatrixColumnView(this, column);
    }
    flipRowView() {
        return new MlMatrixFlipRowView(this);
    }
    flipColumnView() {
        return new MlMatrixFlipColumnView(this);
    }
    subMatrixView(startRow, endRow, startColumn, endColumn) {
        return new MlMatrixSubView(this, startRow, endRow, startColumn, endColumn);
    }
    selectionView(rowIndices, columnIndices) {
        return new MlMatrixSelectionView(this, rowIndices, columnIndices);
    }
    det() {
        if (this.isSquare()) {
            let a;
            let b;
            let c;
            let d;
            if (this.columns === MLINDEX_BYTES_NUM_2) {
                a = this.get(0, 0);
                b = this.get(0, 1);
                c = this.get(1, 0);
                d = this.get(1, 1);
                return a * d - b * c;
            }
            else if (this.columns === MLINDEX_BYTES_NUM_3) {
                let subMatrix0;
                let subMatrix1;
                let subMatrix2;
                subMatrix0 = this.selectionView([1, MLINDEX_BYTES_NUM_2], [1, MLINDEX_BYTES_NUM_2]);
                subMatrix1 = this.selectionView([1, MLINDEX_BYTES_NUM_2], [0, MLINDEX_BYTES_NUM_2]);
                subMatrix2 = this.selectionView([1, MLINDEX_BYTES_NUM_2], [0, 1]);
                a = this.get(0, 0);
                b = this.get(0, 1);
                c = this.get(0, MLINDEX_BYTES_NUM_2);
                return a * subMatrix0.det() - b * subMatrix1.det() + c * subMatrix2.det();
            }
            else {
                // general purpose determinant using the LU decomposition
                return new MlMatrixDclu(this).determinant();
            }
        }
        else {
            throw Error('Determinant can only be calculated for a square matrix.');
        }
    }
    checkDimensions(matrix, otherMatrix) {
        if (matrix.rows !== otherMatrix.rows || matrix.columns !== otherMatrix.columns) {
            throw new RangeError('Matrices dimensions must be equal');
        }
    }
    compareNumbers(a, b) {
        return a - b;
    }
    inverse() {
        return mlMatrixDecompositions.inverse(this);
    }
    inv() {
        return this.inverse();
    }
    solve(other) {
        return mlMatrixDecompositions.solve(this, other);
    }
    add(value) {
        if (typeof value === 'number') {
            return this.addS(value);
        }
        return this.addM(value);
    }
    addS(value) {
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) + value);
            }
        }
        return this;
    }
    addM(matrix) {
        matrix = Matrix.checkMatrix(matrix);
        this.checkDimensions(this, matrix);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) + matrix.get(i, j));
            }
        }
        return this;
    }
    static add(matrix, value) {
        let newMatrix = new Matrix(matrix);
        return newMatrix.add(value);
    }
    sub(value) {
        if (typeof value === 'number') {
            return this.subS(value);
        }
        return this.subM(value);
    }
    subS(value) {
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) - value);
            }
        }
        return this;
    }
    subM(matrix) {
        matrix = Matrix.checkMatrix(matrix);
        this.checkDimensions(this, matrix);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) - matrix.get(i, j));
            }
        }
        return this;
    }
    static sub(matrix, value) {
        let newMatrix = new Matrix(matrix);
        return newMatrix.sub(value);
    }
    mul(value) {
        if (typeof value === 'number') {
            return this.mulS(value);
        }
        return this.mulM(value);
    }
    mulS(value) {
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) * value);
            }
        }
        return this;
    }
    mulM(matrix) {
        matrix = Matrix.checkMatrix(matrix);
        this.checkDimensions(this, matrix);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) * matrix.get(i, j));
            }
        }
        return this;
    }
    static mul(matrix, value) {
        let newMatrix = new Matrix(matrix);
        return newMatrix.mul(value);
    }
    div(value) {
        if (typeof value === 'number') {
            return this.divS(value);
        }
        return this.divM(value);
    }
    divS(value) {
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) / value);
            }
        }
        return this;
    }
    divM(matrix) {
        matrix = Matrix.checkMatrix(matrix);
        this.checkDimensions(this, matrix);
        for (let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.columns; j++) {
                this.set(i, j, this.get(i, j) / matrix.get(i, j));
            }
        }
        return this;
    }
    static div(matrix, value) {
        let newMatrix = new Matrix(matrix);
        return newMatrix.div(value);
    }
    removeRow(index) {
        mlMatrixUtil.checkRowIndex(this, index, false);
        if (this.rows === 1) {
            throw new RangeError('A matrix cannot have less than one row');
        }
        this.rows -= 1;
        return this;
    }
    addRow(index, array) {
        mlMatrixUtil.checkRowIndex(this, index, true);
        mlMatrixUtil.checkRowVector(this, array);
        this.rows += 1;
        return this;
    }
    removeColumn(index) {
        mlMatrixUtil.checkColumnIndex(this, index, false);
        if (this.columns === 1) {
            throw new RangeError('A matrix cannot have less than one column');
        }
        this.columns -= 1;
        return this;
    }
    addColumn(index, array) {
        let newArray = array;
        mlMatrixUtil.checkColumnIndex(this, index, true);
        newArray = mlMatrixUtil.checkColumnVector(this, newArray);
        this.columns += 1;
        return this;
    }
}
Matrix.inverse = (matrix) => {
    return mlMatrixDecompositions.inverse(matrix);
};
Matrix.inv = (matrix) => {
    return mlMatrixDecompositions.inverse(matrix);
};
class MlArrayUtilsArrayUtilsCls {
    coordArrayToPoints(array, dimensions) {
        if (array.length % dimensions !== 0) {
            throw new RangeError('Dimensions number must be accordance with the size of the array.');
        }
        let length = array.length / dimensions;
        let pointsArr = Array(length).fill(null);
        let k = 0;
        let i = 0;
        for (i = 0; i < array.length; i += dimensions) {
            let point = Array(dimensions).fill(null);
            for (let j = 0; j < dimensions; ++j) {
                point[j] = array[i + j];
            }
            pointsArr[k] = point;
            k += 1;
            i += dimensions;
        }
        return pointsArr;
    }
    coordArrayToCoordMatrix(array, dimensions) {
        if (array.length % dimensions !== 0) {
            throw new RangeError('Dimensions number must be accordance with the size of the array.');
        }
        let coordinatesArray = Array(dimensions).fill([0]);
        let points = array.length / dimensions;
        for (let i = 0; i < coordinatesArray.length; i++) {
            coordinatesArray[i] = Array(points).fill(0);
        }
        for (let i = 0; i < array.length; i += dimensions) {
            for (let j = 0; j < dimensions; ++j) {
                let currentPoint = Math.floor(i / dimensions);
                coordinatesArray[j][currentPoint] = array[i + j];
            }
            i += dimensions;
        }
        return coordinatesArray;
    }
    coordMatrixToCoordArray(coordMatrix) {
        let coodinatesArray = Array(coordMatrix.length * coordMatrix[0].length).fill(0);
        let k = 0;
        for (let i = 0; i < coordMatrix[0].length; ++i) {
            for (let j = 0; j < coordMatrix.length; ++j) {
                coodinatesArray[k] = coordMatrix[j][i];
                k += 1;
            }
        }
        return coodinatesArray;
    }
    transpose(matrix) {
        let resultMatrix = Array(matrix[0].length).fill([0]);
        for (let i = 0; i < resultMatrix.length; ++i) {
            resultMatrix[i] = Array(matrix.length).fill(0);
        }
        for (let i = 0; i < matrix.length; ++i) {
            for (let j = 0; j < matrix[i].length; ++j) {
                resultMatrix[j][i] = matrix[i][j];
            }
        }
        return resultMatrix;
    }
    pointsToCoordArray(points) {
        let coodinatesArray = Array(points.length * points[0].length).fill(0);
        let k = 0;
        for (let i = 0; i < points.length; ++i) {
            for (let j = 0; j < points[0].length; ++j) {
                coodinatesArray[k] = points[i][j];
                k += 1;
            }
        }
        return coodinatesArray;
    }
    applyDotProduct(firstVector, secondVector) {
        let largestVector;
        let smallestVector;
        if (firstVector.length <= secondVector.length) {
            smallestVector = firstVector;
            largestVector = secondVector;
        }
        else {
            smallestVector = secondVector;
            largestVector = firstVector;
        }
        let difference = largestVector.length - smallestVector.length + 1;
        let dotProductApplied = Array(difference).fill(0);
        for (let i = 0; i < difference; ++i) {
            let sum = 0;
            for (let j = 0; j < smallestVector.length; ++j) {
                sum += smallestVector[j] * largestVector[i + j];
            }
            dotProductApplied[i] = sum;
        }
        return dotProductApplied;
    }
    scale(input, options) {
        let y;
        if (options.inPlace) {
            y = input;
        }
        else {
            y = Array(input.length).fill(0.0);
        }
        return y;
    }
}
let mlArrayUtilsArrayUtils = new MlArrayUtilsArrayUtilsCls();
// ml-matrix src/views/base
class MlMatrixBaseView extends Matrix {
    constructor(matrix, rows, columns) {
        super(matrix);
        this.matrix = matrix;
        this.rows = rows;
        this.columns = columns;
    }
}
// ml-matrix src/views/column.js
class MlMatrixColumnView extends MlMatrixBaseView {
    constructor(matrix, column) {
        super(matrix, matrix.rows, 1);
        this.column = column;
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(rowIndex, this.column, value);
        return this;
    }
    get(rowIndex) {
        return this.matrix.get(rowIndex, this.column);
    }
}
// ml-matrix src/views/flipColumn.js
class MlMatrixFlipColumnView extends MlMatrixBaseView {
    constructor(matrix) {
        super(matrix, matrix.rows, matrix.columns);
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(rowIndex, this.columns - columnIndex - 1, value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(rowIndex, this.columns - columnIndex - 1);
    }
}
// ml-matrix src/views/flipRow.js
class MlMatrixFlipRowView extends MlMatrixBaseView {
    constructor(matrix) {
        super(matrix, 1, matrix.columns);
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(this.rows - rowIndex - 1, columnIndex, value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(this.rows - rowIndex - 1, columnIndex);
    }
}
// ml-matrix src/views/row.js
class MlMatrixRowView extends MlMatrixBaseView {
    constructor(matrix, row) {
        super(matrix, 1, matrix.columns);
        this.row = row;
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(this.row, columnIndex, value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(this.row, columnIndex);
    }
}
// ml-matrix src/views/selection.js
class MlMatrixSelectionView extends MlMatrixBaseView {
    constructor(matrix, rowIndices, columnIndices) {
        super(matrix, 0, 0);
        let indices = mlMatrixUtil.checkIndices(matrix, rowIndices, columnIndices);
        this.rowIndices = indices[0];
        this.columnIndices = indices[1];
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(this.rowIndices[rowIndex], this.columnIndices[columnIndex], value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(this.rowIndices[rowIndex], this.columnIndices[columnIndex]);
    }
}
// ml-matrix src/views/sub.js
class MlMatrixSubView extends MlMatrixBaseView {
    constructor(matrix, startRow, endRow, startColumn, endColumn) {
        super(matrix, endRow - startRow + 1, endColumn - startColumn + 1);
        mlMatrixUtil.checkRange(matrix, startRow, endRow, startColumn, endColumn);
        this.startRow = startRow;
        this.startColumn = startColumn;
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(this.startRow + rowIndex, this.startColumn + columnIndex, value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(this.startRow + rowIndex, this.startColumn + columnIndex);
    }
}
// ml-matrix src/views/transpose.js
class MlMatrixTransposeView extends MlMatrixBaseView {
    constructor(matrix) {
        super(matrix, matrix.columns, matrix.rows);
    }
    set(rowIndex, columnIndex, value) {
        this.matrix.set(columnIndex, rowIndex, value);
        return this;
    }
    get(rowIndex, columnIndex) {
        return this.matrix.get(columnIndex, rowIndex);
    }
}
// ml-matrix src/dc/cholesky.js
class MlMatrixDcCholesky {
    constructor(value) {
        value = Matrix.checkMatrix(value);
        if (!value.isSymmetric()) {
            throw new Error('Matrix is not symmetric');
        }
        let a = value;
        let dimension = a.rows;
        let l = new Matrix(dimension, dimension);
        let positiveDefinite = true;
        for (let j = 0; j < dimension; j++) {
            let lRowj = l.getRow(j);
            let d = 0.0;
            for (let k = 0; k < j; k++) {
                let lRowk = l.getRow(k);
                let s = 0.0;
                for (let i = 0; i < k; i++) {
                    s += lRowk[i] * lRowj[i];
                }
                s = (a.get(j, k) - s) / l.get(k, k);
                lRowj[k] = s;
                d = d + s * s;
            }
            d = a.get(j, j) - d;
            if (d > 0) {
                positiveDefinite = true;
            }
            else {
                positiveDefinite = false;
            }
            l.set(j, j, Math.sqrt(Math.max(d, 0)));
            for (let k = j + 1; k < dimension; k++) {
                l.set(j, k, 0);
            }
        }
        if (!positiveDefinite) {
            throw new Error('Matrix is not positive definite');
        }
        this.l = l;
    }
    lowerTriangularMatrix() {
        return this.l;
    }
    solve(value) {
        value = Matrix.checkMatrix(value);
        let l = this.l;
        let dimension = l.rows;
        if (value.rows !== dimension) {
            throw new Error('Matrix dimensions do not match');
        }
        let count = value.columns;
        let b = value.clone();
        for (let k = 0; k < dimension; k++) {
            for (let j = 0; j < count; j++) {
                for (let i = 0; i < k; i++) {
                    b.set(k, j, b.get(k, j) - b.get(i, j) * l.get(k, i));
                }
                b.set(k, j, b.get(k, j) / l.get(k, k));
            }
        }
        for (let k = dimension - 1; k >= 0; k--) {
            for (let j = 0; j < count; j++) {
                for (let i = k + 1; i < dimension; i++) {
                    b.set(k, j, b.get(k, j) - b.get(i, j) * l.get(i, k));
                }
                b.set(k, j, b.get(k, j) / l.get(k, k));
            }
        }
        return b;
    }
}
// ml-matrix src/dc/evd.js
class MlMatrixDcevd {
    constructor(matrix, options) {
        this.n = 0;
        this.e = [];
        this.d = [];
        this.v = [[]];
        matrix = Matrix.checkMatrix(matrix);
        if (!matrix.isSquare()) {
            throw new Error('Matrix is not a square matrix');
        }
        let n = matrix.columns;
        let v = mlMatrixDcuTil.getFilled2dArray(n, n, 0);
        let d = Array(n).fill(0.0);
        let e = Array(n).fill(0.0);
        let value = matrix;
        let isSymmetric = false;
        if (options.defaultOptions.get('assumeSymmetric')) {
            isSymmetric = true;
        }
        else {
            isSymmetric = matrix.isSymmetric();
        }
        if (isSymmetric) {
            for (let i = 0; i < n; i++) {
                for (let j = 0; j < n; j++) {
                    v[i][j] = value.get(i, j);
                }
            }
            this.tred2(n, e, d, v);
            this.tql2(n, e, d, v);
        }
        else {
            let h = mlMatrixDcuTil.getFilled2dArray(n, n, 0);
            let ort = Array(n).fill(0.0);
            for (let j = 0; j < n; j++) {
                for (let i = 0; i < n; i++) {
                    h[i][j] = value.get(i, j);
                }
            }
            this.orthes(n, h, ort, v);
            this.hqr2(n, e, d, v, h);
        }
        this.n = n;
        this.e = e;
        this.d = d;
        this.v = v;
    }
    realEigenvalues() {
        return this.d;
    }
    imaginaryEigenvalues() {
        return this.e;
    }
    eigenvectorMatrix() {
        if (!Matrix.isMatrix(this.v)) {
            this.m1 = new Matrix(this.v);
        }
        return this.m1;
    }
    diagonalMatrix() {
        let n = this.n;
        let e = this.e;
        let d = this.d;
        let x = new Matrix(n, n);
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                x.set(i, j, 0);
            }
            x.set(i, i, d[i]);
            if (e[i] > 0) {
                x.set(i, i + 1, e[i]);
            }
            else if (e[i] < 0) {
                x.set(i, i - 1, e[i]);
            }
        }
        return x;
    }
    tred2(n, e, d, v) {
        let f;
        let g;
        let h;
        let hh;
        let scale;
        let ei = e;
        let di = d;
        let vi = v;
        for (let j = 0; j < n; j++) {
            di[j] = vi[n - 1][j];
        }
        for (let i = n - 1; i > 0; i--) {
            scale = 0;
            h = 0;
            for (let k = 0; k < i; k++) {
                scale = scale + Math.abs(di[k]);
            }
            if (scale === 0) {
                ei[i] = di[i - 1];
                for (let j = 0; j < i; j++) {
                    di[j] = vi[i - 1][j];
                    vi[i][j] = 0;
                }
            }
            else {
                for (let k = 0; k < i; k++) {
                    di[k] /= scale;
                    h += di[k] * di[k];
                }
                f = di[i - 1];
                g = Math.sqrt(h);
                if (f > 0) {
                    g = -g;
                }
                ei[i] = scale * g;
                h = h - f * g;
                di[i - 1] = f - g;
                for (let j = 0; j < i; j++) {
                    ei[j] = 0;
                }
                for (let j = 0; j < i; j++) {
                    f = di[j];
                    vi[j][i] = f;
                    g = ei[j] + vi[j][j] * f;
                    for (let k = j + 1; k <= i - 1; k++) {
                        g += vi[k][j] * di[k];
                        ei[k] += vi[k][j] * f;
                    }
                    ei[j] = g;
                }
                f = 0;
                for (let j = 0; j < i; j++) {
                    ei[j] /= h;
                    f += ei[j] * di[j];
                }
                hh = f / (h + h);
                for (let j = 0; j < i; j++) {
                    ei[j] -= hh * di[j];
                }
                for (let j = 0; j < i; j++) {
                    f = di[j];
                    g = ei[j];
                    for (let k = j; k <= i - 1; k++) {
                        vi[k][j] -= f * ei[k] + g * di[k];
                    }
                    di[j] = vi[i - 1][j];
                    vi[i][j] = 0;
                }
            }
            di[i] = h;
        }
        for (let i = 0; i < n - 1; i++) {
            vi[n - 1][i] = vi[i][i];
            vi[i][i] = 1;
            h = di[i + 1];
            if (h !== 0) {
                for (let k = 0; k <= i; k++) {
                    di[k] = vi[k][i + 1] / h;
                }
                for (let j = 0; j <= i; j++) {
                    g = 0;
                    for (let k = 0; k <= i; k++) {
                        g += vi[k][i + 1] * vi[k][j];
                    }
                    for (let k = 0; k <= i; k++) {
                        vi[k][j] -= g * di[k];
                    }
                }
            }
            for (let k = 0; k <= i; k++) {
                vi[k][i + 1] = 0;
            }
        }
        for (let j = 0; j < n; j++) {
            di[j] = vi[n - 1][j];
            vi[n - 1][j] = 0;
        }
        vi[n - 1][n - 1] = 1;
        ei[0] = 0;
    }
    tql2(n, e, d, v) {
        let g;
        let h;
        let k;
        let m;
        let p;
        let r;
        let dl1;
        let c;
        let c2;
        let c3;
        let el1;
        let s;
        let s2;
        let iter;
        let ei = e;
        let di = d;
        let vi = v;
        for (let i = 1; i < n; i++) {
            ei[i - 1] = ei[i];
        }
        ei[n - 1] = 0;
        let f = 0.0;
        let tst1 = 0.0;
        let eps = Math.pow(MLINDEX_BYTES_NUM_20, MLINDEX_BYTES_NUM_0520);
        for (let l = 0; l < n; l++) {
            tst1 = Math.max(tst1, Math.abs(di[l]) + Math.abs(ei[l]));
            m = l;
            while (m < n) {
                if (Math.abs(ei[m]) <= eps * tst1) {
                    break;
                }
                m += 1;
            }
            if (m > l) {
                iter = 0;
                do {
                    iter = iter + 1;
                    g = di[l];
                    p = (di[l + 1] - g) / (MLINDEX_BYTES_NUM_2 * ei[l]);
                    r = mlMatrixDcuTil.hypotenuse(p, 1);
                    if (p < 0) {
                        r = -r;
                    }
                    di[l] = ei[l] / (p + r);
                    di[l + 1] = ei[l] * (p + r);
                    dl1 = di[l + 1];
                    h = g - di[l];
                    for (let i = l + MLINDEX_BYTES_NUM_2; i < n; i++) {
                        di[i] -= h;
                    }
                    f = f + h;
                    p = di[m];
                    c = 1;
                    c2 = c;
                    c3 = c;
                    el1 = ei[l + 1];
                    s = 0;
                    s2 = 0;
                    for (let i = m - 1; i >= l; i--) {
                        c3 = c2;
                        c2 = c;
                        s2 = s;
                        g = c * ei[i];
                        h = c * p;
                        r = mlMatrixDcuTil.hypotenuse(p, ei[i]);
                        ei[i + 1] = s * r;
                        s = ei[i] / r;
                        c = p / r;
                        p = c * di[i] - s * g;
                        di[i + 1] = h + s * (c * g + s * di[i]);
                        for (k = 0; k < n; k++) {
                            h = vi[k][i + 1];
                            vi[k][i + 1] = s * vi[k][i] + c * h;
                            vi[k][i] = c * vi[k][i] - s * h;
                        }
                    }
                    p = (-s * s2 * c3 * el1 * ei[l]) / dl1;
                    ei[l] = s * p;
                    di[l] = c * p;
                } while (Math.abs(ei[l]) > eps * tst1);
            }
            di[l] = di[l] + f;
            ei[l] = 0;
        }
        for (let i = 0; i < n - 1; i++) {
            k = i;
            p = di[i];
            for (let j = i + 1; j < n; j++) {
                if (di[j] < p) {
                    k = j;
                    p = di[j];
                }
            }
            if (k !== i) {
                di[k] = di[i];
                di[i] = p;
                for (let j = 0; j < n; j++) {
                    p = vi[j][i];
                    vi[j][i] = vi[j][k];
                    vi[j][k] = p;
                }
            }
        }
    }
    orthes(n, h, ort, v) {
        let low = 0;
        let high = n - 1;
        let f;
        let g;
        let hl;
        let scale;
        let hi = h;
        let orti = ort;
        let vi = v;
        for (let m = low + 1; m <= high - 1; m++) {
            scale = 0;
            for (let i = m; i <= high; i++) {
                scale = scale + Math.abs(hi[i][m - 1]);
            }
            if (scale !== 0) {
                hl = 0;
                for (let i = high; i >= m; i--) {
                    orti[i] = hi[i][m - 1] / scale;
                    hl += orti[i] * orti[i];
                }
                g = Math.sqrt(Number(h));
                if (orti[m] > 0) {
                    g = -g;
                }
                hl = hl - orti[m] * g;
                orti[m] = orti[m] - g;
                for (let j = m; j < n; j++) {
                    f = 0;
                    for (let i = high; i >= m; i--) {
                        f += orti[i] * hi[i][j];
                    }
                    f = f / hl;
                    for (let i = m; i <= high; i++) {
                        hi[i][j] -= f * orti[i];
                    }
                }
                for (let i = 0; i <= high; i++) {
                    f = 0;
                    for (let j = high; j >= m; j--) {
                        f += orti[j] * hi[i][j];
                    }
                    f = f / hl;
                    for (let j = m; j <= high; j++) {
                        hi[i][j] -= f * orti[j];
                    }
                }
                orti[m] = scale * orti[m];
                hi[m][m - 1] = scale * g;
            }
        }
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                vi[i][j] = i === j ? 1 : 0;
            }
        }
        for (let m = high - 1; m >= low + 1; m--) {
            if (hi[m][m - 1] !== 0) {
                for (let i = m + 1; i <= high; i++) {
                    orti[i] = hi[i][m - 1];
                }
                for (let j = m; j <= high; j++) {
                    g = 0.0;
                    for (let i = m; i <= high; i++) {
                        g += orti[i] * vi[i][j];
                    }
                    g = g / orti[m] / hi[m][m - 1];
                    for (let i = m; i <= high; i++) {
                        vi[i][j] += g * orti[i];
                    }
                }
            }
        }
    }
    hqr2(nn, e, d, v, h) {
        let n = nn - 1;
        let low = 0;
        let high = nn - 1;
        let eps = Math.pow(MLINDEX_BYTES_NUM_20, MLINDEX_BYTES_NUM_0520);
        let exshift = 0.0;
        let norm = 0.0;
        let p = 0.0;
        let q = 0.0;
        let r = 0.0;
        let s = 0.0;
        let z = 0.0;
        let iter = 0.0;
        let l;
        let m;
        let t;
        let w;
        let x;
        let y;
        let ra;
        let sa;
        let vr;
        let vi;
        let notlast;
        let cdivres;
        let nni = nn;
        let ei = e;
        let di = d;
        let vd = v;
        let hi = h;
        for (let i = 0; i < nni; i++) {
            if (i < low || i > high) {
                di[i] = hi[i][i];
                ei[i] = 0;
            }
            for (let j = Math.max(i - 1, 0); j < nni; j++) {
                norm = norm + Math.abs(hi[i][j]);
            }
        }
        while (n >= low) {
            l = n;
            while (l > low) {
                s = Math.abs(hi[l - 1][l - 1]) + Math.abs(hi[l][l]);
                if (s === 0) {
                    s = norm;
                }
                if (Math.abs(hi[l][l - 1]) < eps * s) {
                    break;
                }
                l -= 1;
            }
            if (l === n) {
                hi[n][n] = hi[n][n] + exshift;
                di[n] = hi[n][n];
                ei[n] = 0;
                n -= 1;
                iter = 0;
            }
            else if (l === n - 1) {
                w = hi[n][n - 1] * hi[n - 1][n];
                p = (hi[n - 1][n - 1] - hi[n][n]) / MLINDEX_BYTES_NUM_2;
                q = p * p + w;
                z = Math.sqrt(Math.abs(q));
                hi[n][n] = hi[n][n] + exshift;
                hi[n - 1][n - 1] = hi[n - 1][n - 1] + exshift;
                x = hi[n][n];
                if (q >= 0) {
                    z = p >= 0 ? p + z : p - z;
                    di[n - 1] = x + z;
                    di[n] = di[n - 1];
                    if (z !== 0) {
                        di[n] = x - w / z;
                    }
                    ei[n - 1] = 0;
                    ei[n] = 0;
                    x = hi[n][n - 1];
                    s = Math.abs(x) + Math.abs(z);
                    p = x / s;
                    q = z / s;
                    r = Math.sqrt(p * p + q * q);
                    p = p / r;
                    q = q / r;
                    for (let j = n - 1; j < nni; j++) {
                        z = hi[n - 1][j];
                        hi[n - 1][j] = q * z + p * hi[n][j];
                        hi[n][j] = q * hi[n][j] - p * z;
                    }
                    for (let i = 0; i <= n; i++) {
                        z = hi[i][n - 1];
                        hi[i][n - 1] = q * z + p * hi[i][n];
                        hi[i][n] = q * hi[i][n] - p * z;
                    }
                    for (let i = low; i <= high; i++) {
                        z = vd[i][n - 1];
                        vd[i][n - 1] = q * z + p * vd[i][n];
                        vd[i][n] = q * vd[i][n] - p * z;
                    }
                }
                else {
                    di[n - 1] = x + p;
                    di[n] = x + p;
                    ei[n - 1] = z;
                    ei[n] = -z;
                }
                n = n - MLINDEX_BYTES_NUM_2;
                iter = 0;
            }
            else {
                x = hi[n][n];
                y = 0;
                w = 0;
                if (l < n) {
                    y = hi[n - 1][n - 1];
                    w = hi[n][n - 1] * hi[n - 1][n];
                }
                if (iter === MLINDEX_BYTES_NUM_10) {
                    exshift += x;
                    for (let i = low; i <= n; i++) {
                        hi[i][i] -= x;
                    }
                    s = Math.abs(hi[n][n - 1]) + Math.abs(hi[n - 1][n - MLINDEX_BYTES_NUM_2]);
                    y = MLINDEX_BYTES_NUM_075 * s;
                    x = y;
                    w = MLINDEX_BYTES_NUM_04375 * s * s;
                }
                if (iter === MLINDEX_BYTES_NUM_30) {
                    s = (y - x) / MLINDEX_BYTES_NUM_2;
                    s = s * s + w;
                    if (s > 0) {
                        s = Math.sqrt(s);
                        if (y < x) {
                            s = -s;
                        }
                        s = x - w / ((y - x) / MLINDEX_BYTES_NUM_2 + s);
                        for (let i = low; i <= n; i++) {
                            hi[i][i] -= s;
                        }
                        exshift += s;
                        w = MLINDEX_BYTES_NUM_0964;
                        y = w;
                        x = y;
                    }
                }
                iter = iter + 1;
                m = n - MLINDEX_BYTES_NUM_2;
                while (m >= l) {
                    z = hi[m][m];
                    r = x - z;
                    s = y - z;
                    p = (r * s - w) / hi[m + 1][m] + hi[m][m + 1];
                    q = hi[m + 1][m + 1] - z - r - s;
                    r = hi[m + MLINDEX_BYTES_NUM_2][m + 1];
                    s = Math.abs(p) + Math.abs(q) + Math.abs(r);
                    p = p / s;
                    q = q / s;
                    r = r / s;
                    if (m === l) {
                        break;
                    }
                    if (Math.abs(hi[m][m - 1]) * (Math.abs(q) + Math.abs(r)) <
                        eps * (Math.abs(p) * (Math.abs(hi[m - 1][m - 1]) + Math.abs(z) + Math.abs(hi[m + 1][m + 1])))) {
                        break;
                    }
                    m -= 1;
                }
                for (let i = m + MLINDEX_BYTES_NUM_2; i <= n; i++) {
                    hi[i][i - MLINDEX_BYTES_NUM_2] = 0;
                    if (i > m + MLINDEX_BYTES_NUM_2) {
                        hi[i][i - MLINDEX_BYTES_NUM_3] = 0;
                    }
                }
                for (let k = m; k <= n - 1; k++) {
                    notlast = k !== n - 1;
                    if (k !== m) {
                        p = hi[k][k - 1];
                        q = hi[k + 1][k - 1];
                        r = notlast ? hi[k + MLINDEX_BYTES_NUM_2][k - 1] : 0.0;
                        x = Math.abs(p) + Math.abs(q) + Math.abs(r);
                        if (x !== 0) {
                            p = p / x;
                            q = q / x;
                            r = r / x;
                        }
                    }
                    if (x === 0) {
                        break;
                    }
                    s = Math.sqrt(p * p + q * q + r * r);
                    if (p < 0) {
                        s = -s;
                    }
                    if (s !== 0) {
                        if (k !== m) {
                            hi[k][k - 1] = -s * x;
                        }
                        else if (l !== m) {
                            hi[k][k - 1] = -hi[k][k - 1];
                        }
                        p = p + s;
                        x = p / s;
                        y = q / s;
                        z = r / s;
                        q = q / p;
                        r = r / p;
                        for (let j = k; j < nni; j++) {
                            p = hi[k][j] + q * hi[k + 1][j];
                            if (notlast) {
                                p = p + r * hi[k + MLINDEX_BYTES_NUM_2][j];
                                hi[k + MLINDEX_BYTES_NUM_2][j] = hi[k + MLINDEX_BYTES_NUM_2][j] - p * z;
                            }
                            hi[k][j] = hi[k][j] - p * x;
                            hi[k + 1][j] = hi[k + 1][j] - p * y;
                        }
                        for (let i = 0; i <= Math.min(n, k + MLINDEX_BYTES_NUM_3); i++) {
                            p = x * hi[i][k] + y * hi[i][k + 1];
                            if (notlast) {
                                p = p + z * hi[i][k + MLINDEX_BYTES_NUM_2];
                                hi[i][k + MLINDEX_BYTES_NUM_2] = hi[i][k + MLINDEX_BYTES_NUM_2] - p * r;
                            }
                            hi[i][k] = hi[i][k] - p;
                            hi[i][k + 1] = hi[i][k + 1] - p * q;
                        }
                        for (let i = low; i <= high; i++) {
                            p = x * vd[i][k] + y * vd[i][k + 1];
                            if (notlast) {
                                p = p + z * vd[i][k + MLINDEX_BYTES_NUM_2];
                                vd[i][k + MLINDEX_BYTES_NUM_2] = vd[i][k + MLINDEX_BYTES_NUM_2] - p * r;
                            }
                            vd[i][k] = vd[i][k] - p;
                            vd[i][k + 1] = vd[i][k + 1] - p * q;
                        }
                    }
                }
            }
        }
        if (norm === 0) {
            return;
        }
        for (n = nni - 1; n >= 0; n--) {
            p = di[n];
            q = ei[n];
            if (q === 0) {
                l = n;
                hi[n][n] = 1;
                for (let i = n - 1; i >= 0; i--) {
                    w = hi[i][i] - p;
                    r = 0.0;
                    for (let j = l; j <= n; j++) {
                        r = r + hi[i][j] * hi[j][n];
                    }
                    if (ei[i] < 0) {
                        z = w;
                        s = r;
                    }
                    else {
                        l = i;
                        if (ei[i] === 0) {
                            if (w !== 0) {
                                hi[i][n] = -r / w;
                            }
                            else {
                                hi[i][n] = -r / (eps * norm);
                            }
                        }
                        else {
                            x = hi[i][i + 1];
                            y = hi[i + 1][i];
                            q = (di[i] - p) * (di[i] - p) + ei[i] * ei[i];
                            t = x * s - (z * r) / q;
                            hi[i][n] = t;
                            if (Math.abs(x) > Math.abs(z)) {
                                hi[i + 1][n] = -r - (w * t) / x;
                            }
                            else {
                                hi[i + 1][n] = -s - (y * t) / z;
                            }
                        }
                        t = Math.abs(hi[i][n]);
                        if (eps * t * t > 1) {
                            for (let j = i; j <= n; j++) {
                                hi[j][n] = hi[j][n] / t;
                            }
                        }
                    }
                }
            }
            else if (q < 0) {
                l = n - 1;
                if (Math.abs(hi[n][n - 1]) > Math.abs(hi[n - 1][n])) {
                    hi[n - 1][n - 1] = q / hi[n][n - 1];
                    hi[n - 1][n] = -(hi[n][n] - p) / hi[n][n - 1];
                }
                else {
                    cdivres = this.cdiv(0.0, -Number(hi[n - 1][n]), hi[n - 1][n - 1] - p, q);
                    hi[n - 1][n - 1] = cdivres[0];
                    hi[n - 1][n] = cdivres[1];
                }
                hi[n][n - 1] = 0;
                hi[n][n] = 1;
                for (let i = n - MLINDEX_BYTES_NUM_2; i >= 0; i--) {
                    ra = 0;
                    sa = 0;
                    for (let j = l; j <= n; j++) {
                        ra = ra + hi[i][j] * hi[j][n - 1];
                        sa = sa + hi[i][j] * hi[j][n];
                    }
                    w = hi[i][i] - p;
                    if (ei[i] < 0) {
                        z = w;
                        r = ra;
                        s = sa;
                    }
                    else {
                        l = i;
                        if (ei[i] === 0) {
                            cdivres = this.cdiv(-ra, -sa, w, q);
                            hi[i][n - 1] = cdivres[0];
                            hi[i][n] = cdivres[1];
                        }
                        else {
                            x = hi[i][i + 1];
                            y = hi[i + 1][i];
                            vr = (di[i] - p) * (di[i] - p) + ei[i] * ei[i] - q * q;
                            vi = (di[i] - p) * MLINDEX_BYTES_NUM_2 * q;
                            if (vr === 0 && vi === 0) {
                                vr = eps * norm * (Math.abs(w) + Math.abs(q) + Math.abs(x) + Math.abs(y) + Math.abs(z));
                            }
                            cdivres = this.cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
                            hi[i][n - 1] = cdivres[0];
                            hi[i][n] = cdivres[1];
                            if (Math.abs(x) > Math.abs(z) + Math.abs(q)) {
                                hi[i + 1][n - 1] = (-ra - w * hi[i][n - 1] + q * hi[i][n]) / x;
                                hi[i + 1][n] = (-sa - w * hi[i][n] - q * hi[i][n - 1]) / x;
                            }
                            else {
                                cdivres = this.cdiv(-r - y * hi[i][n - 1], -s - y * hi[i][n], z, q);
                                hi[i + 1][n - 1] = cdivres[0];
                                hi[i + 1][n] = cdivres[1];
                            }
                        }
                        t = Math.max(Math.abs(hi[i][n - 1]), Math.abs(hi[i][n]));
                        if (eps * t * t > 1) {
                            for (let j = i; j <= n; j++) {
                                hi[j][n - 1] = hi[j][n - 1] / t;
                                hi[j][n] = hi[j][n] / t;
                            }
                        }
                    }
                }
            }
        }
        for (let i = 0; i < nni; i++) {
            if (i < low || i > high) {
                for (let j = i; j < nni; j++) {
                    vd[i][j] = hi[i][j];
                }
            }
        }
        for (let j = nni - 1; j >= low; j--) {
            for (let i = low; i <= high; i++) {
                z = 0;
                for (let k = low; k <= Math.min(j, high); k++) {
                    z = z + vd[i][k] * hi[k][j];
                }
                vd[i][j] = z;
            }
        }
    }
    cdiv(xr, xi, yr, yi) {
        let r;
        let d;
        if (Math.abs(yr) > Math.abs(yi)) {
            r = yi / yr;
            d = yr + r * yi;
            return [(xr + r * xi) / d, (xi - r * xr) / d];
        }
        else {
            r = yr / yi;
            d = yi + r * yr;
            return [(r * xr + xi) / d, (r * xi - xr) / d];
        }
    }
}
// ml-matrix src/dc/qr.js
class MlMatrixDcqr {
    constructor(qr) {
        this.rdiag = [];
        this.qr = qr;
    }
    qrDecomposition(value) {
        let newValue = Matrix.checkMatrix(value);
        let qr = newValue.clone();
        let m = newValue.rows;
        let n = newValue.columns;
        let rdiag = Array(n).fill(0);
        let s;
        for (let k = 0; k < n; k++) {
            let nrm = 0;
            for (let i = k; i < m; i++) {
                nrm = mlMatrixDcuTil.hypotenuse(nrm, qr.get(i, k));
            }
            if (nrm !== 0) {
                if (qr.get(k, k) < 0) {
                    nrm = -nrm;
                }
                for (let i = k; i < m; i++) {
                    qr.set(i, k, qr.get(i, k) / nrm);
                }
                qr.set(k, k, qr.get(k, k) + 1);
                for (let j = k + 1; j < n; j++) {
                    s = 0.0;
                    for (let i = k; i < m; i++) {
                        s += qr.get(i, k) * qr.get(i, j);
                    }
                    s = -s / qr.get(k, k);
                    for (let i = k; i < m; i++) {
                        qr.set(i, j, qr.get(i, j) + s * qr.get(i, k));
                    }
                }
            }
            rdiag[k] = -nrm;
        }
        this.qr = qr;
        this.rdiag = rdiag;
    }
    solve(value) {
        let newValue = Matrix.checkMatrix(value);
        let qr = this.qr;
        let m = qr.rows;
        if (newValue.rows !== m) {
            throw new Error('Matrix row dimensions must agree');
        }
        if (!this.isFullRank()) {
            throw new Error('Matrix is rank deficient');
        }
        let count = newValue.columns;
        let x = newValue.clone();
        let n = qr.columns;
        let s;
        for (let k = 0; k < n; k++) {
            for (let j = 0; j < count; j++) {
                s = 0;
                for (let i = k; i < m; i++) {
                    s += qr.get(i, k) * x.get(i, j);
                }
                s = -s / qr.get(k, k);
                for (let i = k; i < m; i++) {
                    x.set(i, j, x.get(i, j) + s * qr.get(i, k));
                }
            }
        }
        for (let k = n - 1; k >= 0; k--) {
            for (let j = 0; j < count; j++) {
                x.set(k, j, x.get(k, j) / this.rdiag[k]);
            }
            for (let i = 0; i < k; i++) {
                for (let j = 0; j < count; j++) {
                    x.set(i, j, x.get(k, j) - x.get(k, j) * qr.get(i, k));
                }
            }
        }
        return x.subMatrix(0, n - 1, 0, count - 1);
    }
    isFullRank() {
        let columns = this.qr.columns;
        for (let i = 0; i < columns; i++) {
            if (this.rdiag[i] === 0) {
                return false;
            }
        }
        return true;
    }
    upperTriangularMatrix() {
        let qr = this.qr;
        let n = qr.columns;
        let x = new Matrix(n, n);
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
                if (i < j) {
                    x.set(i, j, qr.get(i, j));
                }
                else if (i === j) {
                    x.set(i, j, this.rdiag[i]);
                }
                else {
                    x.set(i, j, 0);
                }
            }
        }
        return x;
    }
    orthogonalMatrix() {
        let qr = this.qr;
        let rows = qr.rows;
        let columns = qr.columns;
        let x = new Matrix(rows, columns);
        let s;
        for (let k = columns - 1; k >= 0; k--) {
            for (let i = 0; i < rows; i++) {
                x.set(i, k, 0);
            }
            x.set(k, k, 1.0);
            for (let j = k; j < columns; j++) {
                if (qr.get(k, k) !== 0) {
                    s = 0;
                    for (let i = k; i < rows; i++) {
                        s += qr.get(i, k) * x.get(i, j);
                    }
                    s = -s / qr.get(k, k);
                    for (let i = k; i < rows; i++) {
                        x.set(i, j, x.get(i, j) + s * qr.get(i, k));
                    }
                }
            }
        }
        return x;
    }
}
// ml-matric src/decompositions.js
class MlMatrixDecompositionsCls {
    inverse(matrix) {
        matrix = Matrix.checkMatrix(matrix);
        return mlMatrixDecompositions.solve(matrix, Matrix.eye(matrix.rows));
    }
    solve(leftHandSide, rightHandSide) {
        leftHandSide = Matrix.checkMatrix(leftHandSide);
        rightHandSide = Matrix.checkMatrix(rightHandSide);
        if (leftHandSide.isSquare()) {
            return new MlMatrixDclu(leftHandSide).matrix.solve(rightHandSide);
        }
        else {
            return new MlMatrixDcqr(leftHandSide).solve(rightHandSide);
        }
    }
}
let mlMatrixDecompositions = new MlMatrixDecompositionsCls();
// feedforward-neural-networks utils.js
class FeedforwardNeuralNetworksUtilsCls {
    sumRow(matrix) {
        let sum = Matrix.zeros(matrix.rows, 1);
        for (let i = 0; i < matrix.rows; ++i) {
            for (let j = 0; j < matrix.columns; ++j) {
                sum.set(i, 0, sum.get(i, 0) + matrix.get(i, j));
            }
        }
        return sum;
    }
    sumCol(matrix) {
        let sum = Matrix.zeros(1, matrix.columns);
        for (let i = 0; i < matrix.rows; ++i) {
            for (let j = 0; j < matrix.columns; ++j) {
                sum.set(0, j, sum.get(0, j) + matrix.get(i, j));
            }
        }
        return sum;
    }
    dictOutputs(array) {
        if (Array.isArray(array) && Array.isArray(array[0]) && typeof array[0][0] === 'number') {
            let inputs = new Map();
            let outputs = new Map();
            let index = 0;
            for (let i = 0; i < array.length; i += 1) {
                let key = array[i].toString();
                if (!inputs.has(key)) {
                    inputs.set(key, index);
                    outputs.set(index, array[i]);
                    index += 1;
                }
            }
            return new NeuralNetworkDict(inputs, outputs);
        }
        else if (Array.isArray(array) && typeof array[0] === 'number') {
            let inputs = new Map();
            let outputs = new Map();
            let index = 0;
            for (let i = 0; i < array.length; i += 1) {
                if (inputs.get(array[i]) === undefined) {
                    inputs.set(array[i], index);
                    outputs.set(index, array[i]);
                    index += 1;
                }
            }
            return new NeuralNetworkDict(inputs, outputs);
        }
        else {
            let newArray = array;
            let inputs = new Map();
            let outputs = new Map();
            let index = 0;
            for (let i = 0; i < newArray.length; i += 1) {
                if (inputs.get(newArray[i]) === undefined) {
                    inputs.set(newArray[i], index);
                    outputs.set(index, newArray[i]);
                    index += 1;
                }
            }
            return new NeuralNetworkDict(inputs, outputs);
        }
    }
}
let feedforwardNeuralNetworksUtils = new FeedforwardNeuralNetworksUtilsCls();
class ActivationFuncationTanh {
    constructor() {
        this.name = 'tanh';
        this.paramsCount = 1;
    }
    activation(value) {
        return Math.tanh(value[0]);
    }
    derivate(value) {
        return 1 - value[0] * value[0];
    }
}
class ActivationFuncationIdentity {
    constructor() {
        this.name = 'identity';
        this.paramsCount = 1;
    }
    activation(value) {
        return value[0];
    }
    derivate(value) {
        return 1;
    }
}
class ActivationFuncationLogistic {
    constructor() {
        this.paramsCount = 1;
        this.name = 'logistic';
    }
    logistic(val) {
        return 1 / (1 + Math.exp(-val));
    }
    activation(value) {
        return this.logistic(value[0]);
    }
    derivate(value) {
        return this.logistic(value[0]) * (1 - this.logistic(value[0]));
    }
}
class ActivationFuncationArctan {
    constructor() {
        this.paramsCount = 1;
        this.name = 'arctan';
    }
    activation(value) {
        return Math.atan(value[0]);
    }
    derivate(value) {
        return 1 / (value[0] * value[0] + 1);
    }
}
class ActivationFuncationSoftsign {
    constructor() {
        this.paramsCount = 1;
        this.name = 'softsign';
    }
    activation(value) {
        return value[0] / (1 + Math.abs(value[0]));
    }
    derivate(value) {
        return 1 / ((1 + Math.abs(value[0])) * (1 + Math.abs(value[0])));
    }
}
class ActivationFuncationRelu {
    constructor() {
        this.paramsCount = 1;
        this.name = 'relu';
    }
    activation(value) {
        return value[0] < 0 ? 0 : value[0];
    }
    derivate(value) {
        return value[0] < 0 ? 0 : 1;
    }
}
class ActivationFuncationSoftplus {
    constructor() {
        this.paramsCount = 1;
        this.name = 'softplus';
    }
    activation(value) {
        return Math.log(1 + Math.exp(value[0]));
    }
    derivate(value) {
        return 1 / (1 + Math.exp(-value[0]));
    }
}
class ActivationFuncationBent {
    constructor() {
        this.paramsCount = 1;
        this.name = 'bent';
    }
    activation(value) {
        return (Math.sqrt(value[0] * value[0] + 1) - 1) / MLINDEX_BYTES_NUM_2 + value[0];
    }
    derivate(value) {
        return value[0] / (MLINDEX_BYTES_NUM_2 * Math.sqrt(value[0] * value[0] + 1)) + 1;
    }
}
class ActivationFuncationSinusoid {
    constructor() {
        this.paramsCount = 1;
        this.name = 'sinusoid';
    }
    activation(value) {
        return Math.sin(value[0]);
    }
    derivate(value) {
        return Math.cos(value[0]);
    }
}
class ActivationFuncationSinc {
    constructor() {
        this.paramsCount = 1;
        this.name = 'sinc';
    }
    activation(value) {
        return value[0] === 0 ? 1 : Math.sin(value[0]) / value[0];
    }
    derivate(val) {
        return val[0] === 0 ? 0 : Math.cos(val[0]) / val[0] - Math.sin(val[0]) / (val[0] * val[0]);
    }
}
class ActivationFuncationGaussian {
    constructor() {
        this.paramsCount = 1;
        this.name = 'gaussian';
    }
    activation(val) {
        return Math.exp(-Math.pow(val[0], val[0]));
    }
    derivate(val) {
        return MLINDEX_BYTES_NUM_002 * val[0] * Math.exp(-Math.pow(val[0], val[0]));
    }
}
class ActivationFuncationParametricRelu {
    constructor() {
        this.paramsCount = MLINDEX_BYTES_NUM_2;
        this.name = 'parametric-relu';
    }
    activation(value) {
        if (value.length > 1) {
            return value[0] < 0 ? value[1] * value[0] : value[0];
        }
        else {
            return value[0];
        }
    }
    derivate(value) {
        if (value.length > 1) {
            return value[0] < 0 ? value[1] : 1;
        }
        else {
            return value[0];
        }
    }
}
class ActivationFuncationExponentialElu {
    constructor() {
        this.paramsCount = MLINDEX_BYTES_NUM_2;
        this.name = 'exponential-elu';
    }
    expElu(val, param) {
        return val < 0 ? param * (Math.exp(val) - 1) : val;
    }
    activation(value) {
        return this.expElu(value[0], value[1]);
    }
    derivate(value) {
        return value[0] < 0 ? this.expElu(value[0], value[1]) + value[1] : 1;
    }
}
class ActivationFuncationSoftExponential {
    constructor() {
        this.paramsCount = MLINDEX_BYTES_NUM_2;
        this.name = 'soft-exponential';
    }
    softExponential(val, param) {
        if (param < 0) {
            return -Math.log(1 - param * (val + param)) / param;
        }
        else if (param > 0) {
            return (Math.exp(param * val) - 1) / param + param;
        }
        else {
            return val;
        }
    }
    softExponentialPrime(val, param) {
        if (param < 0) {
            return 1 / (1 - param * (param + val));
        }
        else {
            return Math.exp(param * val);
        }
    }
    activation(value) {
        return this.softExponential(value[0], value[1]);
    }
    derivate(value) {
        return this.softExponentialPrime(value[0], value[1]);
    }
}
let ACTIVATION_FUNCTIONS = [
    new ActivationFuncationTanh(),
    new ActivationFuncationIdentity(),
    new ActivationFuncationLogistic(),
    new ActivationFuncationArctan(),
    new ActivationFuncationSoftsign(),
    new ActivationFuncationRelu(),
    new ActivationFuncationSoftplus(),
    new ActivationFuncationBent(),
    new ActivationFuncationSinusoid(),
    new ActivationFuncationSinc(),
    new ActivationFuncationGaussian(),
    new ActivationFuncationParametricRelu(),
    new ActivationFuncationExponentialElu(),
    new ActivationFuncationSoftExponential()
];
let feedforwardNeuralNetworksActivationFunctions = ACTIVATION_FUNCTIONS;
// feedforward-neural-networks FeedForwardNeuralNetwork.js
class NeuralNetworkDict {
    constructor(inputs, outputs) {
        this.inputs = inputs;
        this.outputs = outputs;
    }
}
class FeedforwardNeuralNetwork {
    constructor(options) {
        this.model = [];
        if (options.model !== undefined) {
            this.hiddenLayers = options.hiddenLayers;
            this.iterations = options.iterations;
            this.learningRate = options.learningRate;
            this.regularization = options.regularization;
            this.dicts = options.dicts;
            this.activation = options.activation;
            this.activationParam = options.activationParam;
            this.model = [];
            for (let i = 0; i < options.layers.length - 1; ++i) {
                this.model.push(FeedforwardNeuralNetworksLayer.load(options.layers[i]));
            }
            this.model.push(new FeedforwardNeuralNetworksOutputLayer(options.layers[options.layers.length - 1]));
        }
        else {
            this.hiddenLayers = options.hiddenLayers.length === 0 ? [MLINDEX_BYTES_NUM_10] : options.hiddenLayers;
            this.iterations = options.iterations === undefined ? MLINDEX_BYTES_NUM_50 : options.iterations;
            this.learningRate = options.learningRate === undefined ? MLINDEX_BYTES_NUM_001 : options.learningRate;
            this.regularization = options.regularization === undefined ? MLINDEX_BYTES_NUM_001 : options.regularization;
            this.activation = options.activation === undefined ? 'tanh' : options.activation;
            this.activationParam = options.activationParam === undefined ? 1 : options.activationParam;
            if (!ACTIVATION_FUNCTIONS.some((fun) => fun.name === this.activation)) {
                this.activation = 'tanh';
            }
        }
    }
    buildNetwork(inputSize, outputSize) {
        MLINDEX_BYTES_NUM_2 + (this.hiddenLayers.length - 1);
        this.model = Array();
        let options = new MlOptions();
        options.inputSize = inputSize;
        options.outputSize = this.hiddenLayers[0];
        options.activation = this.activation;
        options.activationParam = this.activationParam;
        options.regularization = this.regularization;
        options.epsilon = this.learningRate;
        this.model.push(new FeedforwardNeuralNetworksLayer(options));
        for (let i = 1; i < this.hiddenLayers.length; ++i) {
            let option = new MlOptions();
            option.inputSize = this.hiddenLayers[i - 1];
            option.outputSize = this.hiddenLayers[i];
            option.activation = this.activation;
            option.activationParam = this.activationParam;
            option.regularization = this.regularization;
            option.epsilon = this.learningRate;
            this.model.push(new FeedforwardNeuralNetworksLayer(option));
        }
        let optionOut = new MlOptions();
        optionOut.inputSize = this.hiddenLayers[this.hiddenLayers.length - 1];
        optionOut.outputSize = outputSize;
        optionOut.activation = this.activation;
        optionOut.activationParam = this.activationParam;
        optionOut.regularization = this.regularization;
        optionOut.epsilon = this.learningRate;
        this.model.push(new FeedforwardNeuralNetworksOutputLayer(optionOut));
    }
    train(features, labels) {
        features = Matrix.checkMatrix(features);
        this.dicts = feedforwardNeuralNetworksUtils.dictOutputs(labels);
        let inputSize = features.columns;
        let outputSize = this.dicts.inputs.size;
        this.buildNetwork(inputSize, outputSize);
        for (let i = 0; i < this.iterations; ++i) {
            let probabilities = this.propagate(features);
            this.backpropagation(features, labels, probabilities);
        }
    }
    propagate(x) {
        let input = x;
        for (let i = 0; i < this.model.length; ++i) {
            input = this.model[i].forward(input);
        }
        return input.divColumnVector(feedforwardNeuralNetworksUtils.sumRow(input));
    }
    backpropagation(features, labels, probabilities) {
        var _a, _b, _c, _d, _e, _f;
        let newProbabilities = probabilities;
        for (let i = 0; i < newProbabilities.array.length; ++i) {
            let key = labels[i];
            if (typeof key === 'boolean') {
                key = key ? 1 : 0;
                newProbabilities.set(i, (_a = this.dicts) === null || _a === void 0 ? void 0 : _a.inputs.get(key), probabilities.get(i, (_b = this.dicts) === null || _b === void 0 ? void 0 : _b.inputs.get(key)) - 1);
            }
            else {
                if (Array.isArray(labels[i]) && typeof labels[0] === 'number') {
                    let key = labels[i].toString();
                    newProbabilities.set(i, (_c = this.dicts) === null || _c === void 0 ? void 0 : _c.inputs.get(key), probabilities.get(i, (_d = this.dicts) === null || _d === void 0 ? void 0 : _d.inputs.get(key)) - 1);
                }
                else {
                    newProbabilities.set(i, (_e = this.dicts) === null || _e === void 0 ? void 0 : _e.inputs.get(labels[i]), probabilities.get(i, (_f = this.dicts) === null || _f === void 0 ? void 0 : _f.inputs.get(labels[i])) - 1);
                }
            }
        }
        let delta = newProbabilities;
        for (let i = this.model.length - 1; i >= 0; --i) {
            let a = i > 0 ? this.model[i - 1].a : features;
            delta = this.model[i].backpropagation(delta, a);
        }
        for (let i = 0; i < this.model.length; ++i) {
            this.model[i].update();
        }
    }
    predict(features) {
        var _a;
        features = Matrix.checkMatrix(features);
        let outputs = new Array();
        let probabilities = this.propagate(features);
        for (let i = 0; i < features.rows; i++) {
            let result = (_a = this.dicts) === null || _a === void 0 ? void 0 : _a.outputs.get(probabilities.maxRowIndex(i)[1]);
            outputs.push(result);
        }
        return outputs;
    }
    toJSON() {
        let model = new MlOptions();
        model.model = 'FNN';
        model.hiddenLayers = this.hiddenLayers;
        model.iterations = this.iterations;
        model.learningRate = this.learningRate;
        model.regularization = this.regularization;
        model.activation = this.activation;
        model.activationParam = this.activationParam;
        model.dicts = this.dicts;
        model.layers = [];
        for (let i = 0; i < this.model.length; i++) {
            model.layers.push(this.model[i].toJSON());
        }
        return model;
    }
    static load(model) {
        if (model.model !== 'FNN') {
            throw new RangeError('the current model is not a feed forward network');
        }
        return new FeedforwardNeuralNetwork(model);
    }
}
// feedforward-neural-networks Layer.js
class FeedforwardNeuralNetworksLayer {
    constructor(options) {
        this.inputSize = options.inputSize;
        this.outputSize = options.outputSize;
        this.regularization = options.regularization;
        this.epsilon = options.epsilon;
        this.activation = options.activation;
        this.activationParam = options.activationParam;
        let selectedFunction = ACTIVATION_FUNCTIONS.filter((e) => e.name === this.activation)[0];
        let actFunction;
        if (selectedFunction.paramsCount === MLINDEX_BYTES_NUM_2) {
            actFunction = (val) => {
                if (this.activationParam !== undefined) {
                    return selectedFunction.activation([val, this.activationParam]);
                }
                else {
                    return selectedFunction.activation([val, 1]);
                }
            };
        }
        else {
            actFunction = (val) => {
                return selectedFunction.activation([val]);
            };
        }
        this.activationFunction = (matrix, i, j) => {
            matrix.set(i, j, actFunction(matrix.get(i, j)));
        };
        let derFunction;
        if (selectedFunction.paramsCount === MLINDEX_BYTES_NUM_2) {
            derFunction = (val) => {
                return selectedFunction.derivate([val, this.activationParam]);
            };
        }
        else {
            derFunction = (val) => {
                return selectedFunction.derivate([val]);
            };
        }
        this.derivate = (matrix, i, j) => {
            matrix.set(i, j, derFunction(matrix.get(i, j)));
        };
        if (options.model !== undefined) {
            this.w = Matrix.checkMatrix(options.w);
            this.b = Matrix.checkMatrix(options.b);
        }
        else {
            this.w = Matrix.rand(this.inputSize, this.outputSize);
            this.b = Matrix.zeros(1, this.outputSize);
            this.w.apply((matrix, i, j) => {
                matrix.set(i, j, matrix.get(i, j) / Math.sqrt(Number(options.inputSize)));
            });
        }
    }
    forward(x) {
        let z = x.mmul(this.w).addRowVector(this.b);
        z.apply(this.activationFunction);
        this.a = z.clone();
        return z;
    }
    backpropagation(delta, a) {
        this.dw = a.transposeView().mmul(delta);
        this.db = feedforwardNeuralNetworksUtils.sumCol(delta);
        let aCopy = a.clone();
        return delta.mmul(this.w.transposeView()).mul(aCopy.apply(this.derivate));
    }
    update() {
        this.dw.add(this.w.clone().mul(this.regularization));
        this.w.add(this.dw.mul(-this.epsilon));
        this.b.add(this.db.mul(-this.epsilon));
    }
    toJSON() {
        let model = new MlOptions();
        model.model = 'Layer';
        model.inputSize = this.inputSize;
        model.outputSize = this.outputSize;
        model.regularization = this.regularization;
        model.epsilon = this.epsilon;
        model.activation = this.activation;
        model.w = this.w;
        model.b = this.b;
        return model;
    }
    static load(model) {
        if (model.model !== 'Layer') {
            throw new RangeError('the current model is not a Layer model');
        }
        return new FeedforwardNeuralNetworksLayer(model);
    }
}
// feedforward-neural-networks OutputLayer.js
class FeedforwardNeuralNetworksOutputLayer extends FeedforwardNeuralNetworksLayer {
    constructor(options) {
        super(options);
        this.activationFunction = (matrix, i, j) => {
            matrix.set(i, j, Math.exp(matrix.get(i, j)));
        };
    }
    static load1(model) {
        if (model.model !== 'Layer') {
            throw new RangeError('the current model is not a Layer model');
        }
        return new FeedforwardNeuralNetworksOutputLayer(model);
    }
}
/*
 * @State
 * @Tags Jetstream2
 */
class Benchmark {
    it(name, f) {
        f();
    }
    run() {
        let result;
        let functions = ACTIVATION_FUNCTIONS;
        this.it('Training the neural network with XOR operator', () => {
            {
                let source = [
                    [0.0, 0.0],
                    [0.0, 1.0],
                    [1.0, 0.0],
                    [1.0, 1.0]
                ];
                let trainingSet = new Matrix(source);
                let predictions = [0, 1, 1, 0];
                for (let i = 0; i < functions.length; i++) {
                    let options = new MlOptions();
                    options.hiddenLayers = [MLINDEX_BYTES_NUM_4];
                    options.iterations = MLINDEX_BYTES_NUM_040;
                    options.learningRate = MLINDEX_BYTES_NUM_03;
                    options.activation = functions[i].name;
                    let xorNn = new FeedforwardNeuralNetwork(options);
                    xorNn.train(trainingSet, predictions);
                    result = xorNn.predict(trainingSet);
                }
            }
        });
        this.it('Training the neural network with AND operator', () => {
            let trainingSet = [
                [0, 0],
                [0, 1],
                [1, 0],
                [1, 1]
            ];
            let predictions = [
                [1, 0],
                [1, 0],
                [1, 0],
                [0, 1]
            ];
            for (let i = 0; i < functions.length; i++) {
                let options = new MlOptions();
                options.hiddenLayers = [MLINDEX_BYTES_NUM_3];
                options.iterations = MLINDEX_BYTES_NUM_75;
                options.learningRate = MLINDEX_BYTES_NUM_03;
                options.activation = functions[i].name;
                let andNn = new FeedforwardNeuralNetwork(options);
                andNn.train(trainingSet, predictions);
                result = andNn.predict(trainingSet);
            }
        });
        this.it(' and import', () => {
            let trainingSet = [
                [0, 0],
                [0, 1],
                [1, 0],
                [1, 1]
            ];
            let predictions = [0, 1, 1, 1];
            for (let i = 0; i < functions.length; i++) {
                let options = new MlOptions();
                options.hiddenLayers = [MLINDEX_BYTES_NUM_4];
                options.iterations = MLINDEX_BYTES_NUM_040;
                options.learningRate = MLINDEX_BYTES_NUM_03;
                options.activation = functions[i].name;
                let nn = new FeedforwardNeuralNetwork(options);
                nn.train(trainingSet, predictions);
                let model = nn.toJSON();
                let networkNn = FeedforwardNeuralNetwork.load(model);
                result = networkNn.predict(trainingSet);
            }
        });
        this.it('Multiclass clasification', () => {
            let trainingSet = [
                [0, 0],
                [0, 1],
                [1, 0],
                [1, 1]
            ];
            let predictions = [MLINDEX_BYTES_NUM_2, 0, 1, 0];
            for (let i = 0; i < functions.length; i++) {
                let options = new MlOptions();
                options.hiddenLayers = [MLINDEX_BYTES_NUM_4];
                options.iterations = MLINDEX_BYTES_NUM_040;
                options.learningRate = MLINDEX_BYTES_NUM_05;
                options.activation = functions[i].name;
                let nn = new FeedforwardNeuralNetwork(options);
                nn.train(trainingSet, predictions);
                result = nn.predict(trainingSet);
            }
        });
        this.it('Big case', () => {
            let trainingSet = [
                [1, 1],
                [1, MLINDEX_BYTES_NUM_2],
                [MLINDEX_BYTES_NUM_2, 1],
                [MLINDEX_BYTES_NUM_2, MLINDEX_BYTES_NUM_2],
                [MLINDEX_BYTES_NUM_3, 1],
                [1, MLINDEX_BYTES_NUM_3],
                [1, MLINDEX_BYTES_NUM_4],
                [MLINDEX_BYTES_NUM_4, 1],
                [MLINDEX_BYTES_NUM_6, 1],
                [MLINDEX_BYTES_NUM_6, MLINDEX_BYTES_NUM_2],
                [MLINDEX_BYTES_NUM_6, MLINDEX_BYTES_NUM_3],
                [MLINDEX_BYTES_NUM_6, MLINDEX_BYTES_NUM_4],
                [MLINDEX_BYTES_NUM_6, MLINDEX_BYTES_NUM_5],
                [MLINDEX_BYTES_NUM_5, MLINDEX_BYTES_NUM_5],
                [MLINDEX_BYTES_NUM_4, MLINDEX_BYTES_NUM_5],
                [MLINDEX_BYTES_NUM_3, MLINDEX_BYTES_NUM_5]
            ];
            let predictions = [
                [1, 0],
                [1, 0],
                [1, 0],
                [1, 0],
                [1, 0],
                [1, 0],
                [1, 0],
                [1, 0],
                [0, 1],
                [0, 1],
                [0, 1],
                [0, 1],
                [0, 1],
                [0, 1],
                [0, 1],
                [0, 1]
            ];
            for (let i = 0; i < functions.length; i++) {
                let options = new MlOptions();
                options.hiddenLayers = [MLINDEX_BYTES_NUM_020];
                options.iterations = NUM_TIME_LOOP_CONST;
                options.learningRate = MLINDEX_BYTES_NUM_001;
                options.activation = functions[i].name;
                let nn = new FeedforwardNeuralNetwork(options);
                nn.train(trainingSet, predictions);
                result = nn.predict([[MLINDEX_BYTES_NUM_050, MLINDEX_BYTES_NUM_40]]);
            }
        });
    }
    /*
     * @Beanchmark
     */
    runIteration() {
        let start = Date.now();
        for (let i = 0; i < NUM_TIME_LOOP_5; i++) {
            this.run();
        }
        let end = Date.now();
        console.log('ml: ms = ' + (end - start));
    }
}
new Benchmark().runIteration();
